return self.matrix().is_invertible()
+ def is_isometry(self):
+ r"""
+ Return whether or not this operator is an isometry.
+
+ SETUP::
+
+ sage: from mjo.eja.eja_algebra import (ComplexHermitianEJA,
+ ....: HadamardEJA,
+ ....: JordanSpinEJA,
+ ....: RealSymmetricEJA,
+ ....: TrivialEJA,
+ ....: random_eja)
+ sage: from mjo.eja.eja_operator import EJAOperator
+ sage: from mjo.random import random_unitary_matrix
+
+ EXAMPLES:
+
+ The easiest way to construct an isometry is to send an
+ orthonormal basis in one algebra to an orthonormal basis in
+ another::
+
+ sage: J1 = RealSymmetricEJA(2)
+ sage: J2 = JordanSpinEJA(3, prefix='c')
+ sage: M = matrix.identity(J1.base_ring(), 3)
+ sage: L = EJAOperator(J1,J2,M)
+ sage: [ [bi.inner_product(bj) for bi in J1.basis()]
+ ....: for bj in J1.basis() ]
+ [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
+ sage: [ [ci.inner_product(cj) for ci in J2.basis()]
+ ....: for cj in J2.basis() ]
+ [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
+ sage: [ L(b) for b in J1.basis() ]
+ [c0, c1, c2]
+ sage: L.is_isometry()
+ True
+
+ But if you have orthonormal bases on both sides, of course you
+ could use any orthogonal matrix::
+
+ sage: J1 = ComplexHermitianEJA(2)
+ sage: J2 = JordanSpinEJA(4)
+ sage: M = random_unitary_matrix(J1.base_ring(), J1.dimension())
+ sage: L = EJAOperator(J1,J2,M)
+ sage: L.is_isometry()
+ True
+
+ The zero operator is an isometry in a trivial algebra::
+
+ sage: J = TrivialEJA()
+ sage: J.zero().operator().is_isometry()
+ True
+
+ A "famous" non-isometry is to transpose the factors of a
+ cartesian product of two one-dimensional spin algebras where
+ the inner product on one factor is twice the inner product on
+ the other. This is given as a counterexample in Section III.5
+ of Faraut & Koranyi::
+
+ sage: J1 = HadamardEJA(1)
+ sage: J2 = HadamardEJA(1, prefix='c')
+ sage: J2._inner_product_matrix = 2*J1._inner_product_matrix
+ sage: J = cartesian_product([J1,J2])
+ sage: M = matrix(J1.base_ring(), [[0,1],[1,0]])
+ sage: L = EJAOperator(J,J,M)
+ sage: L.is_isometry()
+ False
+
+ TESTS:
+
+ The identity operator is always an isometry::
+
+ sage: J = random_eja()
+ sage: J.one().operator().is_isometry()
+ True
+
+ The zero operator is never an isometry in a nontrivial algebra::
+
+ sage: J = random_eja()
+ sage: not J.is_trivial() and J.zero().operator().is_isometry()
+ False
+
+ """
+ # The basis may not be orthonormalized, so just having an
+ # orthogonal matrix is not sufficient to determine isometry.
+ return all(
+ b1.inner_product(b2) == self(b1).inner_product(self(b2))
+ for b1 in self.domain().basis()
+ for b2 in self.domain().basis()
+ )
+
+
def matrix(self):
"""
Return the matrix representation of this operator with respect