]> gitweb.michael.orlitzky.com - sage.d.git/blobdiff - mjo/eja/euclidean_jordan_algebra.py
eja: remove symmetry test that don't work.
[sage.d.git] / mjo / eja / euclidean_jordan_algebra.py
index 097233fdad86dea01e11483d7b7525f0ab816f2a..849243c81d56a2781a8b0abe5c9e6ae795f264eb 100644 (file)
@@ -5,35 +5,76 @@ are used in optimization, and have some additional nice methods beyond
 what can be supported in a general Jordan Algebra.
 """
 
+from sage.categories.magmatic_algebras import MagmaticAlgebras
+from sage.structure.element import is_Matrix
+from sage.structure.category_object import normalize_names
+
 from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra import FiniteDimensionalAlgebra
 from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_element import FiniteDimensionalAlgebraElement
 
 class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
     @staticmethod
-    def __classcall__(cls, field, mult_table, names='e', category=None):
-        fda = super(FiniteDimensionalEuclideanJordanAlgebra, cls)
-        return fda.__classcall_private__(cls,
-                                         field,
-                                         mult_table,
-                                         names,
-                                         category)
+    def __classcall_private__(cls,
+                              field,
+                              mult_table,
+                              names='e',
+                              assume_associative=False,
+                              category=None,
+                              rank=None):
+        n = len(mult_table)
+        mult_table = [b.base_extend(field) for b in mult_table]
+        for b in mult_table:
+            b.set_immutable()
+            if not (is_Matrix(b) and b.dimensions() == (n, n)):
+                raise ValueError("input is not a multiplication table")
+        mult_table = tuple(mult_table)
+
+        cat = MagmaticAlgebras(field).FiniteDimensional().WithBasis()
+        cat.or_subcategory(category)
+        if assume_associative:
+            cat = cat.Associative()
+
+        names = normalize_names(n, names)
 
-    def __init__(self, field, mult_table, names='e', category=None):
+        fda = super(FiniteDimensionalEuclideanJordanAlgebra, cls)
+        return fda.__classcall__(cls,
+                                 field,
+                                 mult_table,
+                                 assume_associative=assume_associative,
+                                 names=names,
+                                 category=cat,
+                                 rank=rank)
+
+
+    def __init__(self, field,
+                 mult_table,
+                 names='e',
+                 assume_associative=False,
+                 category=None,
+                 rank=None):
+        self._rank = rank
         fda = super(FiniteDimensionalEuclideanJordanAlgebra, self)
-        fda.__init__(field, mult_table, names, category)
+        fda.__init__(field,
+                     mult_table,
+                     names=names,
+                     category=category)
 
 
     def _repr_(self):
         """
         Return a string representation of ``self``.
         """
-        return "Euclidean Jordan algebra of degree {} over {}".format(self.degree(), self.base_ring())
+        fmt = "Euclidean Jordan algebra of degree {} over {}"
+        return fmt.format(self.degree(), self.base_ring())
 
     def rank(self):
         """
         Return the rank of this EJA.
         """
-        raise NotImplementedError
+        if self._rank is None:
+            raise ValueError("no rank specified at genesis")
+        else:
+            return self._rank
 
 
     class Element(FiniteDimensionalAlgebraElement):
@@ -141,7 +182,53 @@ class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
 
 
         def minimal_polynomial(self):
-            return self.matrix().minimal_polynomial()
+            """
+            EXAMPLES::
+
+                sage: set_random_seed()
+                sage: n = ZZ.random_element(1,10).abs()
+                sage: J = eja_rn(n)
+                sage: x = J.random_element()
+                sage: x.degree() == x.minimal_polynomial().degree()
+                True
+
+            ::
+
+                sage: set_random_seed()
+                sage: n = ZZ.random_element(1,10).abs()
+                sage: J = eja_ln(n)
+                sage: x = J.random_element()
+                sage: x.degree() == x.minimal_polynomial().degree()
+                True
+
+            The minimal polynomial and the characteristic polynomial coincide
+            and are known (see Alizadeh, Example 11.11) for all elements of
+            the spin factor algebra that aren't scalar multiples of the
+            identity::
+
+                sage: set_random_seed()
+                sage: n = ZZ.random_element(2,10).abs()
+                sage: J = eja_ln(n)
+                sage: y = J.random_element()
+                sage: while y == y.coefficient(0)*J.one():
+                ....:     y = J.random_element()
+                sage: y0 = y.vector()[0]
+                sage: y_bar = y.vector()[1:]
+                sage: actual = y.minimal_polynomial()
+                sage: x = SR.symbol('x', domain='real')
+                sage: expected = x^2 - 2*y0*x + (y0^2 - norm(y_bar)^2)
+                sage: bool(actual == expected)
+                True
+
+            """
+            V = self.span_of_powers()
+            assoc_subalg = self.subalgebra_generated_by()
+            # Mis-design warning: the basis used for span_of_powers()
+            # and subalgebra_generated_by() must be the same, and in
+            # the same order!
+            subalg_self = assoc_subalg(V.coordinates(self.vector()))
+            return subalg_self.matrix().minimal_polynomial()
+
 
         def characteristic_polynomial(self):
             return self.matrix().characteristic_polynomial()
@@ -180,7 +267,7 @@ def eja_rn(dimension, field=QQ):
     Qs = [ matrix(field, dimension, dimension, lambda k,j: 1*(k == j == i))
            for i in xrange(dimension) ]
 
-    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs)
+    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=dimension)
 
 
 def eja_ln(dimension, field=QQ):
@@ -230,4 +317,4 @@ def eja_ln(dimension, field=QQ):
         Qi[0,0] = Qi[0,0] * ~field(2)
         Qs.append(Qi)
 
-    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs)
+    return FiniteDimensionalEuclideanJordanAlgebra(field,Qs,rank=2)