]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
mjo/eja/eja_operator.py: add is_isometry() method
authorMichael Orlitzky <michael@orlitzky.com>
Tue, 26 Nov 2024 18:33:41 +0000 (13:33 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Tue, 26 Nov 2024 18:33:41 +0000 (13:33 -0500)
mjo/eja/eja_operator.py

index 689b7ecec26c09a8423ca440ee6b00429d50073b..4c1d60ddbf192f4b9fb2909e6934b1e96a559ba2 100644 (file)
@@ -572,6 +572,97 @@ class EJAOperator(Map):
         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