"""
from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis
-from sage.categories.morphism import SetMorphism
+from sage.categories.map import Map
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
-from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_morphism import FiniteDimensionalAlgebraMorphism, FiniteDimensionalAlgebraHomset
-class FiniteDimensionalEuclideanJordanAlgebraHomset(FiniteDimensionalAlgebraHomset):
+class FiniteDimensionalEuclideanJordanAlgebraOperator(Map):
+ def __init__(self, domain_eja, codomain_eja, mat):
+ if not (
+ isinstance(domain_eja, FiniteDimensionalEuclideanJordanAlgebra) and
+ isinstance(codomain_eja, FiniteDimensionalEuclideanJordanAlgebra) ):
+ raise ValueError('(co)domains must be finite-dimensional Euclidean '
+ 'Jordan algebras')
- def has_coerce_map_from(self, S):
- """
- EXAMPLES::
+ F = domain_eja.base_ring()
+ if not (F == codomain_eja.base_ring()):
+ raise ValueError("domain and codomain must have the same base ring")
- sage: J = RealSymmetricEJA(2)
- sage: H = J.Hom(J)
- sage: H.has_coerce_map_from(QQ)
- True
+ # We need to supply something here to avoid getting the
+ # default Homset of the parent FiniteDimensionalAlgebra class,
+ # which messes up e.g. equality testing.
+ parent = Hom(domain_eja, codomain_eja, VectorSpaces(F))
- """
- try:
- # The Homset classes override has_coerce_map_from() with
- # something that crashes when it's given e.g. QQ.
- if S.is_subring(self.codomain().base_ring()):
- return True
- except:
- pclass = super(FiniteDimensionalEuclideanJordanAlgebraHomset, self)
- return pclass.has_coerce_map_from(S)
+ # The Map initializer will set our parent to a homset, which
+ # is explicitly NOT what we want, because these ain't algebra
+ # homomorphisms.
+ super(FiniteDimensionalEuclideanJordanAlgebraOperator,self).__init__(parent)
+ # Keep a matrix around to do all of the real work. It would
+ # be nice if we could use a VectorSpaceMorphism instead, but
+ # those use row vectors that we don't want to accidentally
+ # expose to our users.
+ self._matrix = mat
- def _coerce_map_from_(self, S):
+
+ def _call_(self, x):
"""
+ Allow this operator to be called only on elements of an EJA.
+
EXAMPLES::
- sage: J = RealSymmetricEJA(2)
- sage: H = J.Hom(J)
- sage: H.coerce(2)
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [2 0 0]
- [0 2 0]
- [0 0 2]
+ sage: J = JordanSpinEJA(3)
+ sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: f(x) == x
+ True
"""
- C = self.codomain()
- R = C.base_ring()
- if S.is_subring(R):
- h = S.hom(self.codomain())
- return SetMorphism(Hom(S,C), lambda x: h(x).operator())
+ return self.codomain()(self.matrix()*x.vector())
- def __call__(self, x):
+ def _add_(self, other):
"""
- EXAMPLES::
+ Add the ``other`` EJA operator to this one.
+
+ EXAMPLES:
+
+ When we add two EJA operators, we get another one back::
sage: J = RealSymmetricEJA(2)
- sage: H = J.Hom(J)
- sage: H(2)
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: f + g
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
[2 0 0]
[0 2 0]
[0 0 2]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
+
+ If you try to add two identical vector space operators but on
+ different EJAs, that should blow up::
+
+ sage: J1 = RealSymmetricEJA(2)
+ sage: J2 = JordanSpinEJA(3)
+ sage: id = identity_matrix(QQ, 3)
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,J1,id)
+ sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,J2,id)
+ sage: f + g
+ Traceback (most recent call last):
+ ...
+ TypeError: unsupported operand parent(s) for +: ...
"""
- if x in self.base_ring():
- cols = self.domain().dimension()
- rows = self.codomain().dimension()
- x = x*identity_matrix(self.codomain().base_ring(), rows, cols)
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(self, x)
-
-
- def one(self):
- """
- Return the identity morphism, but as a member of the right
- space (so that we can add it, multiply it, etc.)
- """
- cols = self.domain().dimension()
- rows = self.codomain().dimension()
- mat = identity_matrix(self.base_ring(), rows, cols)
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(self, mat)
-
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ self.domain(),
+ self.codomain(),
+ self.matrix() + other.matrix())
-class FiniteDimensionalEuclideanJordanAlgebraMorphism(FiniteDimensionalAlgebraMorphism):
- """
- A linear map between two finite-dimensional EJAs.
-
- This is a very thin wrapper around FiniteDimensionalAlgebraMorphism
- that does only a few things:
-
- 1. Avoids the ``unitary`` and ``check`` arguments to the constructor
- that will always be ``False``. This is necessary because these
- are homomorphisms with respect to ADDITION, but the SageMath
- machinery wants to check that they're homomorphisms with respect
- to (Jordan) MULTIPLICATION. That obviously doesn't work.
-
- 2. Inputs and outputs the underlying matrix with respect to COLUMN
- vectors, unlike the parent class.
-
- 3. Allows us to add, subtract, negate, multiply (compose), and
- invert morphisms in the obvious way.
-
- If this seems a bit heavyweight, it is. I would have been happy to
- use a the ring morphism that underlies the finite-dimensional
- algebra morphism, but they don't seem to be callable on elements of
- our EJA, and you can't add/multiply/etc. them.
- """
- def _add_(self, other):
+ def _composition_(self, other, homset):
"""
- Add two EJA morphisms in the obvious way.
+ Compose two EJA operators to get another one (and NOT a formal
+ composite object) back.
EXAMPLES::
- sage: J = RealSymmetricEJA(3)
- sage: x = J.zero()
- sage: y = J.one()
- sage: x.operator() + y.operator()
- Morphism from Euclidean Jordan algebra of degree 6 over Rational
- Field to Euclidean Jordan algebra of degree 6 over Rational Field
- given by matrix
- [1 0 0 0 0 0]
- [0 1 0 0 0 0]
- [0 0 1 0 0 0]
- [0 0 0 1 0 0]
- [0 0 0 0 1 0]
- [0 0 0 0 0 1]
-
- TESTS::
-
- sage: set_random_seed()
- sage: J = random_eja()
- sage: x = J.random_element()
- sage: y = J.random_element()
- sage: (x.operator() + y.operator()) in J.Hom(J)
- True
+ sage: J1 = JordanSpinEJA(3)
+ sage: J2 = RealCartesianProductEJA(2)
+ sage: J3 = RealSymmetricEJA(1)
+ sage: mat1 = matrix(QQ, [[1,2,3],
+ ....: [4,5,6]])
+ sage: mat2 = matrix(QQ, [[7,8]])
+ sage: g = FiniteDimensionalEuclideanJordanAlgebraOperator(J1,
+ ....: J2,
+ ....: mat1)
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J2,
+ ....: J3,
+ ....: mat2)
+ sage: f*g
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
+ [39 54 69]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 1 over Rational Field
"""
- P = self.parent()
- if not other in P:
- raise ValueError("summands must live in the same space")
-
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(
- P,
- self.matrix() + other.matrix() )
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ other.domain(),
+ self.codomain(),
+ self.matrix()*other.matrix())
- def __init__(self, parent, f):
- FiniteDimensionalAlgebraMorphism.__init__(self,
- parent,
- f.transpose(),
- unitary=False,
- check=False)
-
+ def __eq__(self, other):
+ if self.domain() != other.domain():
+ return False
+ if self.codomain() != other.codomain():
+ return False
+ if self.matrix() != other.matrix():
+ return False
+ return True
def __invert__(self):
"""
+ Invert this EJA operator.
+
EXAMPLES::
sage: J = RealSymmetricEJA(2)
- sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
- sage: x.is_invertible()
- True
- sage: ~x.operator()
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [-3/2 2 -1/2]
- [ 1 0 0]
- [-1/2 0 1/2]
- sage: x.operator_matrix().inverse()
- [-3/2 2 -1/2]
- [ 1 0 0]
- [-1/2 0 1/2]
-
- TESTS:
-
- Beware, ``x`` being invertible isn't sufficient for its operator
- to be invertible below::
-
- sage: set_random_seed()
- sage: J = random_eja()
- sage: x = J.random_element()
- sage: id = J.Hom(J).one()
- sage: not x.operator_matrix().is_invertible() or (
- ....: ~x.operator()*x.operator() == id )
- True
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: ~f
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
+ [1 0 0]
+ [0 1 0]
+ [0 0 1]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
"""
- A = self.matrix()
- if not A.is_invertible():
- raise ValueError("morphism is not invertible")
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ self.codomain(),
+ self.domain(),
+ ~self.matrix())
- P = self.parent()
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(self.parent(),
- A.inverse())
- def _lmul_(self, right):
+ def __mul__(self, other):
"""
- Compose two EJA morphisms using multiplicative notation.
+ Compose two EJA operators, or scale myself by an element of the
+ ambient vector space.
- EXAMPLES::
+ We need to override the real ``__mul__`` function to prevent the
+ coercion framework from throwing an error when it fails to convert
+ a base ring element into a morphism.
- sage: J = RealSymmetricEJA(2)
- sage: x = J.zero()
- sage: y = J.one()
- sage: x.operator() * y.operator()
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [0 0 0]
- [0 0 0]
- [0 0 0]
+ EXAMPLES:
- ::
+ We can scale an operator on a rational algebra by a rational number::
sage: J = RealSymmetricEJA(2)
- sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
+ sage: e0,e1,e2 = J.gens()
+ sage: x = 2*e0 + 4*e1 + 16*e2
sage: x.operator()
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [ 0 1 0]
- [1/2 1 1/2]
- [ 0 1 2]
- sage: 2*x.operator()
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [0 2 0]
- [1 2 1]
- [0 2 4]
- sage: x.operator()*2
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
- [0 2 0]
- [1 2 1]
- [0 2 4]
-
- TESTS::
-
- sage: set_random_seed()
- sage: J = random_eja()
- sage: x = J.random_element()
- sage: y = J.random_element()
- sage: (x.operator() * y.operator()) in J.Hom(J)
- True
+ Linear operator between finite-dimensional Euclidean Jordan algebras
+ represented by the matrix:
+ [ 2 4 0]
+ [ 2 9 2]
+ [ 0 4 16]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
+ sage: x.operator()*(1/2)
+ Linear operator between finite-dimensional Euclidean Jordan algebras
+ represented by the matrix:
+ [ 1 2 0]
+ [ 1 9/2 1]
+ [ 0 2 8]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
"""
- try:
- # I think the morphism classes break the coercion framework
- # somewhere along the way, so we have to do this ourselves.
- right = self.parent().coerce(right)
- except:
- pass
-
- if not right.codomain() is self.domain():
- raise ValueError("(co)domains must agree for composition")
+ if other in self.codomain().base_ring():
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ self.domain(),
+ self.codomain(),
+ self.matrix()*other)
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(
- self.parent(),
- self.matrix()*right.matrix() )
-
- __mul__ = _lmul_
-
-
- def __pow__(self, n):
- """
-
- TESTS::
-
- sage: J = JordanSpinEJA(4)
- sage: e0,e1,e2,e3 = J.gens()
- sage: x = -5/2*e0 + 1/2*e2 + 20*e3
- sage: Qx = x.quadratic_representation()
- sage: Qx^0
- Morphism from Euclidean Jordan algebra of degree 4 over Rational
- Field to Euclidean Jordan algebra of degree 4 over Rational Field
- given by matrix
- [1 0 0 0]
- [0 1 0 0]
- [0 0 1 0]
- [0 0 0 1]
- sage: (x^0).quadratic_representation() == Qx^0
- True
-
- """
- if n == 0:
- # We get back the stupid identity morphism which doesn't
- # live in the right space.
- return self.parent().one()
- elif n == 1:
- return self
- else:
- return FiniteDimensionalAlgebraMorphism.__pow__(self,n)
+ # This should eventually delegate to _composition_ after performing
+ # some sanity checks for us.
+ mor = super(FiniteDimensionalEuclideanJordanAlgebraOperator,self)
+ return mor.__mul__(other)
def _neg_(self):
"""
- Negate this morphism.
+ Negate this EJA operator.
EXAMPLES::
sage: J = RealSymmetricEJA(2)
- sage: x = J.one()
- sage: -x.operator()
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational Field
- given by matrix
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: -f
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
[-1 0 0]
[ 0 -1 0]
[ 0 0 -1]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
- TESTS::
+ """
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ self.domain(),
+ self.codomain(),
+ -self.matrix())
- sage: set_random_seed()
- sage: J = random_eja()
- sage: x = J.random_element()
- sage: -x.operator() in J.Hom(J)
- True
+
+ def __pow__(self, n):
+ """
+ Raise this EJA operator to the power ``n``.
+
+ TESTS:
+
+ Ensure that we get back another EJA operator that can be added,
+ subtracted, et cetera::
+
+ sage: J = RealSymmetricEJA(2)
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: f^0 + f^1 + f^2
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
+ [3 0 0]
+ [0 3 0]
+ [0 0 3]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
"""
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(
- self.parent(),
- -self.matrix() )
+ if (n == 1):
+ return self
+ elif (n == 0):
+ # Raising a vector space morphism to the zero power gives
+ # you back a special IdentityMorphism that is useless to us.
+ rows = self.codomain().dimension()
+ cols = self.domain().dimension()
+ mat = matrix.identity(self.base_ring(), rows, cols)
+ else:
+ mat = self.matrix()**n
+
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ self.domain(),
+ self.codomain(),
+ mat)
def _repr_(self):
- """
- We override only the representation that is shown to the user,
- because we want the matrix to be with respect to COLUMN vectors.
+ r"""
- TESTS:
+ A text representation of this linear operator on a Euclidean
+ Jordan Algebra.
- Ensure that we see the transpose of the underlying matrix object:
+ EXAMPLES::
- sage: J = RealSymmetricEJA(3)
- sage: x = J.linear_combination(zip(range(len(J.gens())), J.gens()))
- sage: L = x.operator()
- sage: L
- Morphism from Euclidean Jordan algebra of degree 6 over Rational
- Field to Euclidean Jordan algebra of degree 6 over Rational Field
- given by matrix
- [ 0 1 2 0 0 0]
- [1/2 3/2 2 1/2 1 0]
- [ 1 2 5/2 0 1/2 1]
- [ 0 1 0 3 4 0]
- [ 0 1 1/2 2 4 2]
- [ 0 0 2 0 4 5]
- sage: L._matrix
- [ 0 1/2 1 0 0 0]
- [ 1 3/2 2 1 1 0]
- [ 2 2 5/2 0 1/2 2]
- [ 0 1/2 0 3 2 0]
- [ 0 1 1/2 4 4 4]
- [ 0 0 1 0 2 5]
+ sage: J = JordanSpinEJA(2)
+ sage: id = identity_matrix(J.base_ring(), J.dimension())
+ sage: FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
+ [1 0]
+ [0 1]
+ Domain: Euclidean Jordan algebra of degree 2 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 2 over Rational Field
"""
- return "Morphism from {} to {} given by matrix\n{}".format(
- self.domain(), self.codomain(), self.matrix())
+ msg = ("Linear operator between finite-dimensional Euclidean Jordan "
+ "algebras represented by the matrix:\n",
+ "{!r}\n",
+ "Domain: {}\n",
+ "Codomain: {}")
+ return ''.join(msg).format(self.matrix(),
+ self.domain(),
+ self.codomain())
- def __sub__(self, other):
+ def _sub_(self, other):
"""
- Subtract one morphism from another using addition and negation.
+ Subtract ``other`` from this EJA operator.
EXAMPLES::
sage: J = RealSymmetricEJA(2)
- sage: L1 = J.one().operator()
- sage: L1 - L1
- Morphism from Euclidean Jordan algebra of degree 3 over Rational
- Field to Euclidean Jordan algebra of degree 3 over Rational
- Field given by matrix
- [0 0 0]
- [0 0 0]
- [0 0 0]
-
- TESTS::
-
- sage: set_random_seed()
- sage: J = random_eja()
- sage: x = J.random_element()
- sage: y = J.random_element()
- sage: x.operator() - y.operator() in J.Hom(J)
- True
+ sage: id = identity_matrix(J.base_ring(),J.dimension())
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,id)
+ sage: f - (f*2)
+ Linear operator between finite-dimensional Euclidean Jordan
+ algebras represented by the matrix:
+ [-1 0 0]
+ [ 0 -1 0]
+ [ 0 0 -1]
+ Domain: Euclidean Jordan algebra of degree 3 over Rational Field
+ Codomain: Euclidean Jordan algebra of degree 3 over Rational Field
"""
- return self + (-other)
+ return (self + (-other))
def matrix(self):
"""
- Return the matrix of this morphism with respect to a left-action
- on column vectors.
+ Return the matrix representation of this operator with respect
+ to the default bases of its (co)domain.
+
+ EXAMPLES::
+
+ sage: J = RealSymmetricEJA(2)
+ sage: mat = matrix(J.base_ring(), J.dimension(), range(9))
+ sage: f = FiniteDimensionalEuclideanJordanAlgebraOperator(J,J,mat)
+ sage: f.matrix()
+ [0 1 2]
+ [3 4 5]
+ [6 7 8]
+
"""
- return FiniteDimensionalAlgebraMorphism.matrix(self).transpose()
+ return self._matrix
class FiniteDimensionalEuclideanJordanAlgebra(FiniteDimensionalAlgebra):
natural_basis=natural_basis)
- def _Hom_(self, B, cat):
- """
- Construct a homset of ``self`` and ``B``.
- """
- return FiniteDimensionalEuclideanJordanAlgebraHomset(self,
- B,
- category=cat)
-
-
def __init__(self,
field,
mult_table,
determinant).
"""
z = self._a_regular_element()
- V = z.vector().parent().ambient_vector_space()
+ V = self.vector_space()
V1 = V.span_of_basis( (z**k).vector() for k in range(self.rank()) )
b = (V1.basis() + V1.complement().basis())
return V.span_of_basis(b)
else:
return self._rank
+ def vector_space(self):
+ """
+ Return the vector space that underlies this algebra.
+
+ EXAMPLES::
+
+ sage: J = RealSymmetricEJA(2)
+ sage: J.vector_space()
+ Vector space of dimension 3 over Rational Field
+
+ """
+ return self.zero().vector().parent().ambient_vector_space()
+
class Element(FiniteDimensionalAlgebraElement):
"""
"""
P = self.parent()
- return FiniteDimensionalEuclideanJordanAlgebraMorphism(
- Hom(P,P),
+ return FiniteDimensionalEuclideanJordanAlgebraOperator(
+ P,P,
self.operator_matrix() )
sage: bool(lhs == rhs)
True
+ Ensure that our operator's ``matrix`` method agrees with
+ this implementation::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: x = J.random_element()
+ sage: x.operator().matrix() == x.operator_matrix()
+ True
+
"""
fda_elt = FiniteDimensionalAlgebraElement(self.parent(), self)
return fda_elt.matrix().transpose()
sage: 2*Qxy == (x+y).quadratic_representation() - Qx - Qy
True
- Property 2:
+ Property 2 (multiply on the right for :trac:`28272`):
sage: alpha = QQ.random_element()
- sage: (alpha*x).quadratic_representation() == (alpha^2)*Qx
+ sage: (alpha*x).quadratic_representation() == Qx*(alpha^2)
True
Property 3:
#
# We do the extra ambient_vector_space() in case we're messing
# with polynomials and the direct parent is a module.
- V = self.vector().parent().ambient_vector_space()
+ V = self.parent().vector_space()
return V.span( (self**d).vector() for d in xrange(V.dimension()) )