If computing my determinant will be fast, we do so and compare
with zero (Proposition II.2.4 in Faraut and
- Koranyi). Otherwise, Proposition II.3.2 in Faraut and Koranyi
+ Korányi). Otherwise, Proposition II.3.2 in Faraut and Korányi
reduces the problem to the invertibility of my quadratic
representation.
# we want the negative of THAT for the trace.
return -p(*self.to_vector())
- def operator_inner_product(self, other):
+
+ def trace_inner_product(self, other):
+ """
+ Return the trace inner product of myself and ``other``.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import random_eja
+
+ TESTS:
+
+ The trace inner product is commutative, bilinear, and associative::
+
+ sage: J = random_eja()
+ sage: x,y,z = J.random_elements(3)
+ sage: # commutative
+ sage: x.trace_inner_product(y) == y.trace_inner_product(x)
+ True
+ sage: # bilinear
+ sage: a = J.base_ring().random_element()
+ sage: actual = (a*(x+z)).trace_inner_product(y)
+ sage: expected = ( a*x.trace_inner_product(y) +
+ ....: a*z.trace_inner_product(y) )
+ sage: actual == expected
+ True
+ sage: actual = x.trace_inner_product(a*(y+z))
+ sage: expected = ( a*x.trace_inner_product(y) +
+ ....: a*x.trace_inner_product(z) )
+ sage: actual == expected
+ True
+ sage: # associative
+ sage: (x*y).trace_inner_product(z) == y.trace_inner_product(x*z)
+ True
+
+ """
+ if not other in self.parent():
+ raise TypeError("'other' must live in the same algebra")
+
+ return (self*other).trace()
+
+
+ def trace_norm(self):
+ """
+ The norm of this element with respect to :meth:`trace_inner_product`.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
+ ....: HadamardEJA)
+
+ EXAMPLES::
+
+ sage: J = HadamardEJA(2)
+ sage: x = sum(J.gens())
+ sage: x.trace_norm()
+ 1.414213562373095?
+
+ ::
+
+ sage: J = JordanSpinEJA(4)
+ sage: x = sum(J.gens())
+ sage: x.trace_norm()
+ 2.828427124746190?
+
+ """
+ return self.trace_inner_product(self).sqrt()
+
+
+ def operator_trace_inner_product(self, other):
r"""
Return the operator inner product of myself and ``other``.
Euclidean Jordan algebra, this is another associative inner
product under which the cone of squares is symmetric.
- This *probably* works even if the basis hasn't been
- orthonormalized because the eigenvalues of the corresponding
- matrix don't change when the basis does (they're preserved by
- any similarity transformation).
+ This works even if the basis hasn't been orthonormalized
+ because the eigenvalues of the corresponding matrix don't
+ change when the basis does (they're preserved by any
+ similarity transformation).
SETUP::
sage: x,y = J.random_elements(2)
sage: n = J.dimension()
sage: r = J.rank()
- sage: actual = x.operator_inner_product(y)
+ sage: actual = x.operator_trace_inner_product(y)
sage: expected = (n/r)*x.trace_inner_product(y)
sage: actual == expected
True
sage: x,y = J.random_elements(2)
sage: n = J.dimension()
sage: r = J.rank()
- sage: actual = x.operator_inner_product(y)
+ sage: actual = x.operator_trace_inner_product(y)
sage: expected = (n/r)*x.trace_inner_product(y)
sage: actual == expected
True
sage: x,y = J.random_elements(2)
sage: n = J.dimension()
sage: r = J.rank()
- sage: actual = x.operator_inner_product(y)
+ sage: actual = x.operator_trace_inner_product(y)
sage: expected = (n/r)*x.trace_inner_product(y)
sage: actual == expected
True
sage: J = random_eja()
sage: x,y,z = J.random_elements(3)
sage: # commutative
- sage: x.operator_inner_product(y) == y.operator_inner_product(x)
+ sage: actual = x.operator_trace_inner_product(y)
+ sage: expected = y.operator_trace_inner_product(x)
+ sage: actual == expected
True
sage: # bilinear
sage: a = J.base_ring().random_element()
- sage: actual = (a*(x+z)).operator_inner_product(y)
- sage: expected = ( a*x.operator_inner_product(y) +
- ....: a*z.operator_inner_product(y) )
+ sage: actual = (a*(x+z)).operator_trace_inner_product(y)
+ sage: expected = ( a*x.operator_trace_inner_product(y) +
+ ....: a*z.operator_trace_inner_product(y) )
sage: actual == expected
True
- sage: actual = x.operator_inner_product(a*(y+z))
- sage: expected = ( a*x.operator_inner_product(y) +
- ....: a*x.operator_inner_product(z) )
+ sage: actual = x.operator_trace_inner_product(a*(y+z))
+ sage: expected = ( a*x.operator_trace_inner_product(y) +
+ ....: a*x.operator_trace_inner_product(z) )
sage: actual == expected
True
sage: # associative
- sage: actual = (x*y).operator_inner_product(z)
- sage: expected = y.operator_inner_product(x*z)
+ sage: actual = (x*y).operator_trace_inner_product(z)
+ sage: expected = y.operator_trace_inner_product(x*z)
sage: actual == expected
True
- """
- if not other in self.parent():
- raise TypeError("'other' must live in the same algebra")
-
- return (self*other).operator().matrix().trace()
+ Despite the fact that the implementation uses a matrix representation,
+ the answer is independent of the basis used::
-
- def trace_inner_product(self, other):
- """
- Return the trace inner product of myself and ``other``.
-
- SETUP::
-
- sage: from mjo.eja.eja_algebra import random_eja
-
- TESTS:
-
- The trace inner product is commutative, bilinear, and associative::
-
- sage: J = random_eja()
- sage: x,y,z = J.random_elements(3)
- sage: # commutative
- sage: x.trace_inner_product(y) == y.trace_inner_product(x)
- True
- sage: # bilinear
- sage: a = J.base_ring().random_element()
- sage: actual = (a*(x+z)).trace_inner_product(y)
- sage: expected = ( a*x.trace_inner_product(y) +
- ....: a*z.trace_inner_product(y) )
- sage: actual == expected
- True
- sage: actual = x.trace_inner_product(a*(y+z))
- sage: expected = ( a*x.trace_inner_product(y) +
- ....: a*x.trace_inner_product(z) )
+ sage: J = RealSymmetricEJA(3, field=QQ, orthonormalize=False)
+ sage: V = RealSymmetricEJA(3)
+ sage: x,y = J.random_elements(2)
+ sage: w = V(x.to_matrix())
+ sage: z = V(y.to_matrix())
+ sage: expected = x.operator_trace_inner_product(y)
+ sage: actual = w.operator_trace_inner_product(z)
sage: actual == expected
True
- sage: # associative
- sage: (x*y).trace_inner_product(z) == y.trace_inner_product(x*z)
- True
"""
if not other in self.parent():
raise TypeError("'other' must live in the same algebra")
- return (self*other).trace()
+ return (self*other).operator().matrix().trace()
- def trace_norm(self):
+ def operator_trace_norm(self):
"""
- The norm of this element with respect to :meth:`trace_inner_product`.
+ The norm of this element with respect to
+ :meth:`operator_trace_inner_product`.
SETUP::
sage: from mjo.eja.eja_algebra import (JordanSpinEJA,
....: HadamardEJA)
- EXAMPLES::
+ EXAMPLES:
+
+ On a simple algebra, this will differ from :meth:`trace_norm`
+ by the scalar factor ``(n/r).sqrt()``, where `n` is the
+ dimension of the algebra and `r` its rank. This follows from
+ the corresponding result (Proposition III.4.2 of Faraut and
+ Korányi) for the trace inner product::
sage: J = HadamardEJA(2)
sage: x = sum(J.gens())
- sage: x.trace_norm()
+ sage: x.operator_trace_norm()
1.414213562373095?
::
sage: J = JordanSpinEJA(4)
sage: x = sum(J.gens())
- sage: x.trace_norm()
- 2.828427124746190?
+ sage: x.operator_trace_norm()
+ 4
"""
- return self.trace_inner_product(self).sqrt()
+ return self.operator_trace_inner_product(self).sqrt()
class CartesianProductParentEJAElement(EJAElement):