from sage.categories.magmatic_algebras import MagmaticAlgebras
from sage.combinat.free_module import CombinatorialFreeModule
-from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement
-from mjo.misc import _all2list
+from mjo.clan.clan_element import ClanElement
class UnitalClan(CombinatorialFreeModule):
- Element = IndexedFreeModuleElement
+ Element = ClanElement
def __init__(self,
- basis,
+ vector_space,
clan_product,
inner_product,
- field=QQ,
- prefix='c',
- check_axioms=True):
-
- n = len(basis)
- if n == 0:
- raise ValueError("not yet")
-
- associative = None
- commutative = None
- if n <= 1:
- # All zero- and one-dimensional algebras are just the real
- # numbers with (some positive multiples of) the usual
- # multiplication as its Jordan and inner-product.
- associative = True
- commutative = True
-
- if associative is None:
- # We should figure it out. As with check_axioms, we have to do
- # this without the help of the _jordan_product_is_associative()
- # method because we need to know the category before we
- # initialize the algebra.
- associative = all( clan_product(clan_product(bi,bj),bk)
- ==
- clan_product(bi,clan_product(bj,bk))
- for bi in basis
- for bj in basis
- for bk in basis )
-
- # Compute the multiplication tables and inner-product matrix.
- self._inner_product_matrix = matrix.identity(field, n)
- clan_mult = [ [ None for j in range(n) ]
- for i in range(n) ]
-
- for i in range(n):
- for j in range(n):
- clan_mult[i][j] = clan_product(basis[i], basis[j])
- if j <= i+1:
- ip = inner_product(basis[i], basis[j])
- self._inner_product_matrix[i,j] = ip
- self._inner_product_matrix[j,i] = ip
- self._inner_product_matrix._cache = {'hermitian': True}
- self._inner_product_matrix.set_immutable()
-
- if commutative is None:
- commutative = all( clan_mult[i][j] == clan_mult[j][i]
- for i in range(n)
- for j in range(n) )
-
- category = MagmaticAlgebras(field).FiniteDimensional()
- category = category.WithBasis().Unital()
-
- if associative:
- category = category.Associative()
- if commutative:
- category = category.Commutative()
-
- # Call the superclass constructor so that we can use its from_vector()
- # method to build our multiplication table.
+ scalar_field=QQ,
+ category=None,
+ prefix=None,
+ bracket=False):
+
+ self._vector_space = vector_space
+ basis = vector_space.basis()
+ n = vector_space.dimension()
+
+ category = MagmaticAlgebras(scalar_field).or_subcategory(category)
+ category = category.FiniteDimensional().WithBasis().Unital()
+
+ # Compute the multiplication table.
+ self._mt = { i: { j : clan_product(basis[i], basis[j])
+ for j in basis.keys() }
+ for i in basis.keys() }
+
+ # Use the vector_space basis keys so we can convert
+ # easily between them.
CombinatorialFreeModule.__init__(self,
- field,
- range(n),
- prefix=prefix,
+ scalar_field,
+ vector_space.basis().keys(),
category=category,
- bracket=False)
-
- # Now we have to compute the multiplication table by turning
- # whatever the input basis was into vectors whose coordinates
- # we can compute.
- self._input_basis = basis
- self._input_basis_space = self._input_basis[0].parent()
-
- # Now create the vector space for the algebra, which will have
- # its own set of non-ambient coordinates (in terms of the
- # supplied basis).
- degree = len(_all2list(basis[0]))
-
- # Build an ambient space that fits our matrix basis when
- # written out as "long vectors."
- V = VectorSpace(field, degree)
- vector_basis = tuple( V(_all2list(b)) for b in basis )
-
- # Save the span of our matrix basis (when written out as long
- # vectors) because otherwise we'll have to reconstruct it
- # every time we want to coerce a matrix into the algebra.
- self._input_basis_span = V.span_of_basis( vector_basis )
-
- for i in range(n):
- for j in range(n):
- # The jordan product returns a matrixy answer, so we
- # have to convert it to the algebra coordinates.
- elt = clan_mult[i][j]
- elt = self._input_basis_span.coordinate_vector(V(_all2list(elt)))
- clan_mult[i][j] = self.from_vector(elt)
-
- self._multiplication_table = clan_mult
- if check_axioms:
- pass
+ prefix=prefix,
+ bracket=bracket)
+
+ # Now that the CFM has been initialized, we can coerce
+ # elements into it to update the multiplication table.
+ for i in basis.keys():
+ for j in basis.keys():
+ # The basis keys are the same in this CFM as they are
+ # in the vector space, so we can just sum the terms
+ # of each entry in the multiplication table.
+ self._mt[i][j] = self.sum_of_terms(self._mt[i][j].items())
+
def _coerce_map_from_base_ring(self):
"""
"""
return None
+
def product_on_basis(self, i, j):
r"""
Returns the Jordan product of the `i` and `j`th basis elements.
by our superclass machinery to implement :meth:`product`.
"""
- return self._multiplication_table[i][j]
-
-
- def inner_product(self, x, y):
- """
- The inner product associated with this clan.
- """
- B = self._inner_product_matrix
- return (B*x.to_vector()).inner_product(y.to_vector())
+ return self._mt[i][j]