We use a random random seed by default now finally.
The inverse is generally an inverse::
- sage: set_random_seed()
sage: n = ZZ.random_element(10)
sage: M = MatrixSpace(QQ,n)
sage: X = M.random_element()
The face generated by <whatever> should be a face::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: S = ( K.random_element() for idx in range(5) )
sage: F = face_generated_by(K, S)
The face generated by a set should always contain that set::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: S = ( K.random_element() for idx in range(5) )
sage: F = face_generated_by(K, S)
The generators of a proper cone are all extreme vectors of the cone,
and therefore generate their own faces::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8,
....: max_rays=10,
....: strictly_convex=True,
that ``x`` is in the relative interior of ``F`` if and only if
``F`` is the face generated by ``x`` [Tam]_::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: x = K.random_element()
sage: S = [x]
and ``G`` in the face lattice is equal to the face generated by
``F + G`` (in the Minkowski sense) [Tam]_::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: L = K.face_lattice()
sage: F = L.random_element()
Combining Proposition 3.1 and Corollary 3.9 in [Tam]_ gives the
following equality for any ``y`` in ``K``::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: y = K.random_element()
sage: S = [y]
The dual face of ``K`` with respect to itself should be the
lineality space of its dual [Tam]_::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: K_dual = K.dual()
sage: lKd_gens = ( dir*l for dir in [1,-1] for l in K_dual.lines() )
If ``K`` is proper, then the dual face of its trivial face is the
dual of ``K`` [Tam]_::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8,
....: max_rays=10,
....: strictly_convex=True,
The dual of the cone of ``K`` at ``y`` is the dual face of the face
of ``K`` generated by ``y`` ([Tam]_ Corollary 3.2)::
- sage: set_random_seed()
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
sage: y = K.random_element()
sage: S = [y]
Since all faces of a polyhedral cone are exposed, the dual face of a
dual face should be the original face [HilgertHofmannLawson]_::
- sage: set_random_seed()
sage: def check_prop(K,F):
....: return dual_face(K.dual(), dual_face(K,F)).is_equivalent(F)
sage: K = random_cone(max_ambient_dim=8, max_rays=10)
The nonnegative orthant is a proper cone::
- sage: set_random_seed()
sage: n = ZZ.random_element(10)
sage: K = nonnegative_orthant(n)
sage: K.is_proper()
As is the nonnegative orthant::
- sage: set_random_seed()
sage: K = nonnegative_orthant(ZZ.random_element(5))
sage: is_permutation_invariant(K)
True
cone should sum to a nonnegative number (this tests that the
generators really are what we think they are)::
- sage: set_random_seed()
sage: def _has_rearrangement_property(v,p):
....: return sum( sorted(v)[0:p] ) >= 0
sage: all( _has_rearrangement_property(
The rearrangenent cone of order ``p`` is contained in the rearrangement
cone of order ``p + 1`` by [Jeong]_ Proposition 5.2.1::
- sage: set_random_seed()
sage: n = ZZ.random_element(2,10)
sage: p = ZZ.random_element(1,n)
sage: K1 = rearrangement_cone(p,n)
rearrangement cone of order ``n - p`` when ``p`` is less than ``n``,
by [Jeong]_ Proposition 5.2.1::
- sage: set_random_seed()
sage: n = ZZ.random_element(2,10)
sage: p = ZZ.random_element(1,n)
sage: K1 = rearrangement_cone(p,n)
[GourionSeeger]_, whose elements' entries are in non-increasing
order::
- sage: set_random_seed()
sage: n = ZZ.random_element(10)
sage: K = schur_cone(n).dual()
sage: x = K.random_element()
The Schur cone induces the majorization ordering::
- sage: set_random_seed()
sage: def majorized_by(x,y):
....: return (all(sum(x[0:i]) <= sum(y[0:i])
....: for i in range(x.degree()-1))
Well, it doesn't crash at least::
- sage: set_random_seed()
sage: V = VectorSpace(QQ, 2)
sage: A = random_symmetric_pd(V)
sage: A.matrix_space()
Well, it doesn't crash at least::
- sage: set_random_seed()
sage: V = VectorSpace(QQ, 2)
sage: A = random_symmetric_psd(V)
sage: A.matrix_space()
A matrix with the desired rank is returned::
- sage: set_random_seed()
sage: V = VectorSpace(QQ, 5)
sage: A = random_symmetric_psd(V,False,1)
sage: A.rank()
If the user asks for a rank that's too high, we fail::
- sage: set_random_seed()
sage: V = VectorSpace(QQ, 2)
sage: A = random_symmetric_psd(V,False,3)
Traceback (most recent call last):
We should compute that an element subalgebra is associative even
if we circumvent the element method::
- sage: set_random_seed()
sage: J = random_eja(field=QQ,orthonormalize=False)
sage: x = J.random_element()
sage: A = x.subalgebra_generated_by(orthonormalize=False)
TESTS::
- sage: set_random_seed()
sage: J = random_eja()
sage: J(1)
Traceback (most recent call last):
TESTS::
- sage: set_random_seed()
sage: J = random_eja()
sage: n = J.dimension()
sage: bi = J.zero()
Our inner product is "associative," which means the following for
a symmetric bilinear form::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y,z = J.random_elements(3)
sage: (x*y).inner_product(z) == y.inner_product(x*z)
Ensure that this is the usual inner product for the algebras
over `R^n`::
- sage: set_random_seed()
sage: J = HadamardEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = x.inner_product(y)
one). This is in Faraut and Koranyi, and also my "On the
symmetry..." paper::
- sage: set_random_seed()
sage: J = BilinearFormEJA.random_instance()
sage: n = J.dimension()
sage: x = J.random_element()
The values we've presupplied to the constructors agree with
the computation::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.is_associative() == J._jordan_product_is_associative()
True
Ensure that we can convert any element back and forth
faithfully between its matrix and algebra representations::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: J(x.to_matrix()) == x
Our inner product is "associative," which means the following for
a symmetric bilinear form::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y,z = J.random_elements(3)
sage: (x*y).inner_product(z) == y.inner_product(x*z)
Ensure that this is the usual inner product for the algebras
over `R^n`::
- sage: set_random_seed()
sage: J = HadamardEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = x.inner_product(y)
one). This is in Faraut and Koranyi, and also my "On the
symmetry..." paper::
- sage: set_random_seed()
sage: J = BilinearFormEJA.random_instance()
sage: n = J.dimension()
sage: x = J.random_element()
The identity element acts like the identity, regardless of
whether or not we orthonormalize::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: J.one()*x == x and x*J.one() == x
::
- sage: set_random_seed()
sage: J = random_eja(field=QQ, orthonormalize=False)
sage: x = J.random_element()
sage: J.one()*x == x and x*J.one() == x
regardless of the base field and whether or not we
orthonormalize::
- sage: set_random_seed()
sage: J = random_eja()
sage: actual = J.one().operator().matrix()
sage: expected = matrix.identity(J.base_ring(), J.dimension())
::
- sage: set_random_seed()
sage: J = random_eja(field=QQ, orthonormalize=False)
sage: actual = J.one().operator().matrix()
sage: expected = matrix.identity(J.base_ring(), J.dimension())
Ensure that the cached unit element (often precomputed by
hand) agrees with the computed one::
- sage: set_random_seed()
sage: J = random_eja()
sage: cached = J.one()
sage: J.one.clear_cache()
::
- sage: set_random_seed()
sage: J = random_eja(field=QQ, orthonormalize=False)
sage: cached = J.one()
sage: J.one.clear_cache()
Every algebra decomposes trivially with respect to its identity
element::
- sage: set_random_seed()
sage: J = random_eja()
sage: J0,J5,J1 = J.peirce_decomposition(J.one())
sage: J0.dimension() == 0 and J5.dimension() == 0
elements in the two subalgebras are the projections onto their
respective subspaces of the superalgebra's identity element::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: if not J.is_trivial():
The theory shows that these are all homogeneous polynomials of
a known degree::
- sage: set_random_seed()
sage: J = random_eja()
sage: all(p.is_homogeneous() for p in J._charpoly_coefficients())
True
positive integer rank, unless the algebra is trivial in
which case its rank will be zero::
- sage: set_random_seed()
sage: J = random_eja()
sage: r = J.rank()
sage: r in ZZ
Ensure that computing the rank actually works, since the ranks
of all simple algebras are known and will be cached by default::
- sage: set_random_seed() # long time
sage: J = random_eja() # long time
sage: cached = J.rank() # long time
sage: J.rank.clear_cache() # long time
Our basis is normalized with respect to the algebra's inner
product, unless we specify otherwise::
- sage: set_random_seed()
sage: J = ConcreteEJA.random_instance()
sage: all( b.norm() == 1 for b in J.gens() )
True
natural->EJA basis representation is an isometry and within the
EJA the operator is self-adjoint by the Jordan axiom::
- sage: set_random_seed()
sage: J = ConcreteEJA.random_instance()
sage: x = J.random_element()
sage: x.operator().is_self_adjoint()
TESTS::
- sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
sage: A = MatrixSpace(QQ, n)
sage: B = MatrixEJA._denormalized_basis(A)
::
- sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
sage: A = ComplexMatrixAlgebra(n, scalars=QQ)
sage: B = MatrixEJA._denormalized_basis(A)
::
- sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
sage: A = QuaternionMatrixAlgebra(n, scalars=QQ)
sage: B = MatrixEJA._denormalized_basis(A)
::
- sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
sage: A = OctonionMatrixAlgebra(n, scalars=QQ)
sage: B = MatrixEJA._denormalized_basis(A)
The dimension of this algebra is `(n^2 + n) / 2`::
- sage: set_random_seed()
sage: d = RealSymmetricEJA._max_random_instance_dimension()
sage: n = RealSymmetricEJA._max_random_instance_size(d)
sage: J = RealSymmetricEJA(n)
The Jordan multiplication is what we think it is::
- sage: set_random_seed()
sage: J = RealSymmetricEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = (x*y).to_matrix()
The dimension of this algebra is `n^2`::
- sage: set_random_seed()
sage: d = ComplexHermitianEJA._max_random_instance_dimension()
sage: n = ComplexHermitianEJA._max_random_instance_size(d)
sage: J = ComplexHermitianEJA(n)
The Jordan multiplication is what we think it is::
- sage: set_random_seed()
sage: J = ComplexHermitianEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = (x*y).to_matrix()
The dimension of this algebra is `2*n^2 - n`::
- sage: set_random_seed()
sage: d = QuaternionHermitianEJA._max_random_instance_dimension()
sage: n = QuaternionHermitianEJA._max_random_instance_size(d)
sage: J = QuaternionHermitianEJA(n)
The Jordan multiplication is what we think it is::
- sage: set_random_seed()
sage: J = QuaternionHermitianEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = (x*y).to_matrix()
matrix. We opt not to orthonormalize the basis, because if we
did, we would have to normalize the `s_{i}` in a similar manner::
- sage: set_random_seed()
sage: n = ZZ.random_element(5)
sage: M = matrix.random(QQ, max(0,n-1), algorithm='unimodular')
sage: B11 = matrix.identity(QQ,1)
Ensure that we have the usual inner product on `R^n`::
- sage: set_random_seed()
sage: J = JordanSpinEJA.random_instance()
sage: x,y = J.random_elements(2)
sage: actual = x.inner_product(y)
The Jordan product is inherited from our factors and implemented by
our CombinatorialFreeModule Cartesian product superclass::
- sage: set_random_seed()
sage: J1 = HadamardEJA(2)
sage: J2 = RealSymmetricEJA(2)
sage: J = cartesian_product([J1,J2])
The cached unit element is the same one that would be computed::
- sage: set_random_seed() # long time
sage: J1 = random_eja() # long time
sage: J2 = random_eja() # long time
sage: J = cartesian_product([J1,J2]) # long time
The answer never changes::
- sage: set_random_seed()
sage: J1 = random_eja()
sage: J2 = random_eja()
sage: J = cartesian_product([J1,J2])
The answer never changes::
- sage: set_random_seed()
sage: J1 = random_eja()
sage: J2 = random_eja()
sage: J = cartesian_product([J1,J2])
produce the identity map, and mismatching them should produce
the zero map::
- sage: set_random_seed()
sage: J1 = random_eja()
sage: J2 = random_eja()
sage: J = cartesian_product([J1,J2])
TESTS::
- sage: set_random_seed()
sage: n = ZZ.random_element(1,5)
sage: J = random_eja(max_dimension=n, field=QQ, orthonormalize=False)
sage: J.dimension() <= n
The definition of `x^2` is the unambiguous `x*x`::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x*x == (x^2)
True
A few examples of power-associativity::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x*(x*x)*(x*x) == x^5
True
We also know that powers operator-commute (Koecher, Chapter
III, Corollary 1)::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: m = ZZ.random_element(0,10)
sage: n = ZZ.random_element(0,10)
We should always get back an element of the algebra::
- sage: set_random_seed()
sage: p = PolynomialRing(AA, 't').random_element()
sage: J = random_eja()
sage: x = J.random_element()
The characteristic polynomial of an element should evaluate
to zero on that element::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: p = x.characteristic_polynomial()
sage: x.apply_univariate_polynomial(p).is_zero()
Ensure that we can always compute an inner product, and that
it gives us back a real number::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y = J.random_elements(2)
sage: x.inner_product(y) in RLF
The definition of a Jordan algebra says that any element
operator-commutes with its square::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x.operator_commutes_with(x^2)
True
Test Lemma 1 from Chapter III of Koecher::
- sage: set_random_seed()
sage: u,v = random_eja().random_elements(2)
sage: lhs = u.operator_commutes_with(u*v)
sage: rhs = v.operator_commutes_with(u^2)
Test the first polarization identity from my notes, Koecher
Chapter III, or from Baes (2.3)::
- sage: set_random_seed()
sage: x,y = random_eja().random_elements(2)
sage: Lx = x.operator()
sage: Ly = y.operator()
Test the second polarization identity from my notes or from
Baes (2.4)::
- sage: set_random_seed()
sage: x,y,z = random_eja().random_elements(3)
sage: Lx = x.operator()
sage: Ly = y.operator()
Test the third polarization identity from my notes or from
Baes (2.5)::
- sage: set_random_seed()
sage: u,y,z = random_eja().random_elements(3)
sage: Lu = u.operator()
sage: Ly = y.operator()
An element is invertible if and only if its determinant is
non-zero::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x.is_invertible() == (x.det() != 0)
True
Ensure that the determinant is multiplicative on an associative
subalgebra as in Faraut and Korányi's Proposition II.2.2::
- sage: set_random_seed()
sage: J = random_eja().random_element().subalgebra_generated_by()
sage: x,y = J.random_elements(2)
sage: (x*y).det() == x.det()*y.det()
The determinant in real matrix algebras is the usual determinant::
- sage: set_random_seed()
sage: X = matrix.random(QQ,3)
sage: X = X + X.T
sage: J1 = RealSymmetricEJA(3)
The inverse in the spin factor algebra is given in Alizadeh's
Example 11.11::
- sage: set_random_seed()
sage: J = JordanSpinEJA.random_instance()
sage: x = J.random_element()
sage: while not x.is_invertible():
The identity element is its own inverse::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.one().inverse() == J.one()
True
If an element has an inverse, it acts like one::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: (not x.is_invertible()) or (x.inverse()*x == J.one())
The inverse of the inverse is what we started with::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: (not x.is_invertible()) or (x.inverse().inverse() == x)
of an element is the inverse of its left-multiplication operator
applied to the algebra's identity, when that inverse exists::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: (not x.operator().is_invertible()) or (
Check that the fast (cached) and slow algorithms give the same
answer::
- sage: set_random_seed() # long time
sage: J = random_eja(field=QQ, orthonormalize=False) # long time
sage: x = J.random_element() # long time
sage: while not x.is_invertible(): # long time
The identity element is always invertible::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.one().is_invertible()
True
The zero element is never invertible in a non-trivial algebra::
- sage: set_random_seed()
sage: J = random_eja()
sage: (not J.is_trivial()) and J.zero().is_invertible()
False
Test that the fast (cached) and slow algorithms give the same
answer::
- sage: set_random_seed() # long time
sage: J = random_eja(field=QQ, orthonormalize=False) # long time
sage: x = J.random_element() # long time
sage: slow = x.is_invertible() # long time
The identity element is minimal only in an EJA of rank one::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.rank() == 1 or not J.one().is_primitive_idempotent()
True
A non-idempotent cannot be a minimal idempotent::
- sage: set_random_seed()
sage: J = JordanSpinEJA(4)
sage: x = J.random_element()
sage: (not x.is_idempotent()) and x.is_primitive_idempotent()
idempotent if and only if it's idempotent with trace equal to
unity::
- sage: set_random_seed()
sage: J = JordanSpinEJA(4)
sage: x = J.random_element()
sage: expected = (x.is_idempotent() and x.trace() == 1)
Primitive idempotents must be non-zero::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.zero().is_idempotent()
True
The identity element is never nilpotent, except in a trivial EJA::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.one().is_nilpotent() and not J.is_trivial()
False
The additive identity is always nilpotent::
- sage: set_random_seed()
sage: random_eja().zero().is_nilpotent()
True
The zero element should never be regular, unless the parent
algebra has dimension less than or equal to one::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.dimension() <= 1 or not J.zero().is_regular()
True
The unit element isn't regular unless the algebra happens to
consist of only its scalar multiples::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.dimension() <= 1 or not J.one().is_regular()
True
In the spin factor algebra (of rank two), all elements that
aren't multiples of the identity are regular::
- sage: set_random_seed()
sage: J = JordanSpinEJA.random_instance()
sage: n = J.dimension()
sage: x = J.random_element()
The zero and unit elements are both of degree one in nontrivial
algebras::
- sage: set_random_seed()
sage: J = random_eja()
sage: d = J.zero().degree()
sage: (J.is_trivial() and d == 0) or d == 1
Our implementation agrees with the definition::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x.degree() == x.minimal_polynomial().degree()
True
always the same, except in trivial algebras where the minimal
polynomial of the unit/zero element is ``1``::
- sage: set_random_seed()
sage: J = random_eja()
sage: mu = J.one().minimal_polynomial()
sage: t = mu.parent().gen()
The degree of an element is (by one definition) the degree
of its minimal polynomial::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: x.degree() == x.minimal_polynomial().degree()
True
identity. We require the dimension of the algebra to be at least
two here so that said elements actually exist::
- sage: set_random_seed()
sage: d_max = JordanSpinEJA._max_random_instance_dimension()
sage: n = ZZ.random_element(2, max(2,d_max))
sage: J = JordanSpinEJA(n)
The minimal polynomial should always kill its element::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: p = x.minimal_polynomial()
sage: x.apply_univariate_polynomial(p)
The minimal polynomial is invariant under a change of basis,
and in particular, a re-scaling of the basis::
- sage: set_random_seed()
sage: d_max = RealSymmetricEJA._max_random_instance_dimension()
sage: d = ZZ.random_element(1, d_max)
sage: n = RealSymmetricEJA._max_random_instance_size(d)
TESTS::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y = J.random_elements(2)
sage: x.operator()(y) == x*y
The explicit form in the spin factor algebra is given by
Alizadeh's Example 11.12::
- sage: set_random_seed()
sage: x = JordanSpinEJA.random_instance().random_element()
sage: x_vec = x.to_vector()
sage: Q = matrix.identity(x.base_ring(), 0)
Test all of the properties from Theorem 11.2 in Alizadeh::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y = J.random_elements(2)
sage: Lx = x.operator()
This subalgebra, being composed of only powers, is associative::
- sage: set_random_seed()
sage: x0 = random_eja().random_element()
sage: A = x0.subalgebra_generated_by()
sage: x,y,z = A.random_elements(3)
Squaring in the subalgebra should work the same as in
the superalgebra::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: A = x.subalgebra_generated_by()
sage: A(x^2) == A(x)*A(x)
element... unless the original algebra was trivial, in which
case the subalgebra is trivial too::
- sage: set_random_seed()
sage: A = random_eja().zero().subalgebra_generated_by()
sage: (A.is_trivial() and A.dimension() == 0) or A.dimension() == 1
True
where there are non-nilpotent elements, or that we get the dumb
solution in the trivial algebra::
- sage: set_random_seed()
sage: J = random_eja()
sage: x = J.random_element()
sage: while x.is_nilpotent() and not J.is_trivial():
The trace of an element is a real number::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.random_element().trace() in RLF
True
The trace is linear::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y = J.random_elements(2)
sage: alpha = J.base_ring().random_element()
The trace inner product is commutative, bilinear, and associative::
- sage: set_random_seed()
sage: J = random_eja()
sage: x,y,z = J.random_elements(3)
sage: # commutative
The left-multiplication-by-zero operation on a given algebra
is its zero map::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.zero().operator().is_zero()
True
The identity operator is its own inverse::
- sage: set_random_seed()
sage: J = random_eja()
sage: idJ = J.one().operator()
sage: idJ.inverse() == idJ
The inverse of the inverse is the operator we started with::
- sage: set_random_seed()
sage: x = random_eja().random_element()
sage: L = x.operator()
sage: not L.is_invertible() or (L.inverse().inverse() == L)
The identity operator is always invertible::
- sage: set_random_seed()
sage: J = random_eja()
sage: J.one().operator().is_invertible()
True
The zero operator is never invertible in a nontrivial algebra::
- sage: set_random_seed()
sage: J = random_eja()
sage: not J.is_trivial() and J.zero().operator().is_invertible()
False
The matrix representation of an element in the subalgebra is
the same as its matrix representation in the superalgebra::
- sage: set_random_seed()
sage: x = random_eja(field=QQ,orthonormalize=False).random_element()
sage: A = x.subalgebra_generated_by(orthonormalize=False)
sage: y = A.random_element()
works like it does in the superalgebra, even if we orthonormalize
our basis::
- sage: set_random_seed()
sage: x = random_eja(field=AA).random_element()
sage: A = x.subalgebra_generated_by(orthonormalize=True)
sage: y = A.random_element()
We can convert back and forth faithfully::
- sage: set_random_seed()
sage: J = random_eja(field=QQ, orthonormalize=False)
sage: x = J.random_element()
sage: A = x.subalgebra_generated_by(orthonormalize=False)
Conjugating twice gets you the original element::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: x.conjugate().conjugate() == x
This method is idempotent::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: x.real().real() == x.real()
This method is idempotent::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: x.imag().imag() == x.imag()
The norm is nonnegative and belongs to the base field::
- sage: set_random_seed()
sage: O = Octonions()
sage: n = O.random_element().norm()
sage: n >= 0 and n in O.base_ring()
The norm is homogeneous::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: alpha = O.base_ring().random_element()
TESTS::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: x.is_zero() or ( x*x.inverse() == O.one() )
This gives the correct unit element::
- sage: set_random_seed()
sage: O = Octonions()
sage: x = O.random_element()
sage: x*O.one() == x and O.one()*x == x
TESTS::
- sage: set_random_seed()
sage: A = OctonionMatrixAlgebra(ZZ.random_element(10))
sage: x = A.random_element()
sage: x*A.one() == x and A.one()*x == x
TESTS::
- sage: set_random_seed()
sage: A = QuaternionMatrixAlgebra(ZZ.random_element(10))
sage: x = A.random_element()
sage: x*A.one() == x and A.one()*x == x
TESTS::
- sage: set_random_seed()
sage: A = ComplexMatrixAlgebra(ZZ.random_element(10))
sage: x = A.random_element()
sage: x*A.one() == x and A.one()*x == x
TESTS::
- sage: set_random_seed()
sage: entries = QuaternionAlgebra(QQ,-1,-1)
sage: M = MatrixAlgebra(3, entries, QQ)
sage: M.random_element().matrix_space() == M
If we get a zero remainder, then the numerator should belong to
the ideal generated by the denominators::
- sage: set_random_seed()
sage: R = PolynomialRing(QQ, 'x,y,z')
sage: x,y,z = R.gens()
sage: s = ZZ.random_element(1,5).abs()
times the denominators, and the remainder's monomials aren't divisible
by the leading term of any denominator::
- sage: set_random_seed()
sage: R = PolynomialRing(QQ, 'x,y,z')
sage: s = ZZ.random_element(1,5).abs()
sage: gs = [ R.random_element() for idx in range(s) ]
should always get a zero remainder if we divide an element of a
monomial ideal by its generators::
- sage: set_random_seed()
sage: R = PolynomialRing(QQ,'x,y,z')
sage: gs = R.random_element().monomials()
sage: I = R.ideal(gs)