return (self + (-other))
+ def inverse(self):
+ """
+ Return the inverse of this operator, if it exists.
+
+ The reason this method is not simply an alias for the built-in
+ :meth:`__invert__` is that the built-in inversion is a bit magic
+ since it's intended to be a unary operator. If we alias ``inverse``
+ to ``__invert__``, then we wind up having to call e.g. ``A.inverse``
+ without parentheses.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import RealSymmetricEJA, random_eja
+
+ EXAMPLES::
+
+ sage: J = RealSymmetricEJA(2)
+ sage: x = sum(J.gens())
+ sage: x.operator().inverse().matrix()
+ [3/2 -1 1/2]
+ [ -1 2 -1]
+ [1/2 -1 3/2]
+ sage: x.operator().matrix().inverse()
+ [3/2 -1 1/2]
+ [ -1 2 -1]
+ [1/2 -1 3/2]
+
+ TESTS:
+
+ The identity operator is its own inverse::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: idJ = J.one().operator()
+ sage: idJ.inverse() == idJ
+ True
+
+ The zero operator is never invertible::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: J.zero().operator().inverse()
+ Traceback (most recent call last):
+ ...
+ ZeroDivisionError: input matrix must be nonsingular
+
+ """
+ return ~self
+
+
+ def is_invertible(self):
+ """
+ Return whether or not this operator is invertible.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import RealSymmetricEJA, random_eja
+
+ EXAMPLES::
+
+ sage: J = RealSymmetricEJA(2)
+ sage: x = sum(J.gens())
+ sage: x.operator().matrix()
+ [ 1 1/2 0]
+ [1/2 1 1/2]
+ [ 0 1/2 1]
+ sage: x.operator().matrix().is_invertible()
+ True
+ sage: x.operator().is_invertible()
+ True
+
+ TESTS:
+
+ The identity operator is always invertible::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: J.one().operator().is_invertible()
+ True
+
+ The zero operator is never invertible::
+
+ sage: set_random_seed()
+ sage: J = random_eja()
+ sage: J.zero().operator().is_invertible()
+ False
+
+ """
+ return self.matrix().is_invertible()
+
+
def matrix(self):
"""
Return the matrix representation of this operator with respect
sage: x = sum(J.gens())
sage: A = x.subalgebra_generated_by(orthonormalize_basis=True)
sage: L0x = A(x).operator()
- sage: Ps = [ P*l for (l,P) in L0x.spectral_decomposition() ]
- sage: Ps[0] + Ps[1] == L0x
+ sage: sd = L0x.spectral_decomposition()
+ sage: l0 = sd[0][0]
+ sage: l1 = sd[1][0]
+ sage: P0 = sd[0][1]
+ sage: P1 = sd[1][1]
+ sage: P0*l0 + P1*l1 == L0x
+ True
+ sage: P0 + P1 == P0^0 # the identity
+ True
+ sage: P0^2 == P0
+ True
+ sage: P1^2 == P1
+ True
+ sage: c0 = P0(A.one())
+ sage: c1 = P1(A.one())
+ sage: c0.inner_product(c1) == 0
+ True
+ sage: c0 + c1 == A.one()
+ True
+ sage: c0.is_idempotent()
+ True
+ sage: c1.is_idempotent()
True
"""