True
"""
- return tuple( self.random_element() for idx in range(count) )
-
-
- def _rank_computation(self):
- r"""
- Compute the rank of this algebra.
-
- SETUP::
-
- sage: from mjo.eja.eja_algebra import (HadamardEJA,
- ....: JordanSpinEJA,
- ....: RealSymmetricEJA,
- ....: ComplexHermitianEJA,
- ....: QuaternionHermitianEJA)
-
- EXAMPLES::
-
- sage: J = HadamardEJA(4)
- sage: J._rank_computation() == J.rank()
- True
- sage: J = JordanSpinEJA(4)
- sage: J._rank_computation() == J.rank()
- True
- sage: J = RealSymmetricEJA(3)
- sage: J._rank_computation() == J.rank()
- True
- sage: J = ComplexHermitianEJA(2)
- sage: J._rank_computation() == J.rank()
- True
- sage: J = QuaternionHermitianEJA(2)
- sage: J._rank_computation() == J.rank()
- True
-
- """
- n = self.dimension()
- if n == 0:
- return 0
- elif n == 1:
- return 1
-
- var_names = [ "X" + str(z) for z in range(1,n+1) ]
- R = PolynomialRing(self.base_ring(), var_names)
- vars = R.gens()
-
- def L_x_i_j(i,j):
- # From a result in my book, these are the entries of the
- # basis representation of L_x.
- return sum( vars[k]*self.monomial(k).operator().matrix()[i,j]
- for k in range(n) )
-
- L_x = matrix(R, n, n, L_x_i_j)
- x_powers = [ vars[k]*(L_x**k)*self.one().to_vector()
- for k in range(n) ]
-
- # Can assume n >= 2
- M = matrix([x_powers[0]])
- old_rank = 1
-
- for d in range(1,n):
- M = matrix(M.rows() + [x_powers[d]])
- M.echelonize()
- new_rank = M.rank()
- if new_rank == old_rank:
- return new_rank
- else:
- old_rank = new_rank
-
- return n
+ return tuple( self.random_element() for idx in range(count) )
+ @cached_method
def rank(self):
"""
Return the rank of this EJA.
ALGORITHM:
- The author knows of no algorithm to compute the rank of an EJA
- where only the multiplication table is known. In lieu of one, we
- require the rank to be specified when the algebra is created,
- and simply pass along that number here.
+ We first compute the polynomial "column matrices" `p_{k}` that
+ evaluate to `x^k` on the coordinates of `x`. Then, we begin
+ adding them to a matrix one at a time, and trying to solve the
+ system that makes `p_{0}`,`p_{1}`,..., `p_{s-1}` add up to
+ `p_{s}`. This will succeed only when `s` is the rank of the
+ algebra, as proven in a recent draft paper of mine.
SETUP::
sage: r > 0 or (r == 0 and J.is_trivial())
True
+ Ensure that computing the rank actually works, since the ranks
+ of all simple algebras are known and will be cached by default::
+
+ sage: J = HadamardEJA(4)
+ sage: J.rank.clear_cache()
+ sage: J.rank()
+ 4
+
+ ::
+
+ sage: J = JordanSpinEJA(4)
+ sage: J.rank.clear_cache()
+ sage: J.rank()
+ 2
+
+ ::
+
+ sage: J = RealSymmetricEJA(3)
+ sage: J.rank.clear_cache()
+ sage: J.rank()
+ 3
+
+ ::
+
+ sage: J = ComplexHermitianEJA(2)
+ sage: J.rank.clear_cache()
+ sage: J.rank()
+ 2
+
+ ::
+
+ sage: J = QuaternionHermitianEJA(2)
+ sage: J.rank.clear_cache()
+ sage: J.rank()
+ 2
+
"""
- return self._rank
+ n = self.dimension()
+ if n == 0:
+ return 0
+ elif n == 1:
+ return 1
+
+ var_names = [ "X" + str(z) for z in range(1,n+1) ]
+ R = PolynomialRing(self.base_ring(), var_names)
+ vars = R.gens()
+
+ def L_x_i_j(i,j):
+ # From a result in my book, these are the entries of the
+ # basis representation of L_x.
+ return sum( vars[k]*self.monomial(k).operator().matrix()[i,j]
+ for k in range(n) )
+
+ L_x = matrix(R, n, n, L_x_i_j)
+ x_powers = [ vars[k]*(L_x**k)*self.one().to_vector()
+ for k in range(n) ]
+
+ # Can assume n >= 2
+ M = matrix([x_powers[0]])
+ old_rank = 1
+
+ for d in range(1,n):
+ M = matrix(M.rows() + [x_powers[d]])
+ M.echelonize()
+ # TODO: we've basically solved the system here.
+ # We should save the echelonized matrix somehow
+ # so that it can be reused in the charpoly method.
+ new_rank = M.rank()
+ if new_rank == old_rank:
+ return new_rank
+ else:
+ old_rank = new_rank
+
+ return n
def vector_space(self):