]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
mjo/clan: factor out up_hat, down_hat, etc. for matrix clans
authorMichael Orlitzky <michael@orlitzky.com>
Mon, 26 Jan 2026 02:35:59 +0000 (21:35 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Mon, 26 Jan 2026 02:35:59 +0000 (21:35 -0500)
mjo/clan/unital_clan.py

index 46ed222ace8b89be078f27e506e1ed02dfea6845..5ad9b514f9a66322ce8f756398911bda00cf57ed 100644 (file)
@@ -187,6 +187,76 @@ class MatrixClan(NormalDecomposition):
     r"""
     A clan arising from a T-algebra of Hermitian matrices.
     """
+    @staticmethod
+    def _up_hat(x):
+        r"""
+        The "up-hat" function on a T-algebra.
+
+        This is the "top half" of a matrix, in the sense that we keep
+        the strictly upper-triangular part, and keep half of the
+        diagonal (so that ``up_hat(x) + down_hat(x) == x``. It is
+        defined by Vinberg on page 381, and is used to construct a
+        clan whose associated cone equals that of the the T-algebra.
+        """
+        one = x.base_ring().one()
+        two = 2*one
+        return x.parent().sum_of_terms(
+            (idx, a*c)
+            for (idx, c) in x.items()
+            if idx[0] <= idx[1]
+            if (a := one - (idx[0] == idx[1])/two)
+        )
+
+    @staticmethod
+    def _down_hat(x):
+        r"""
+        The "down-hat" function on a T-algebra.
+
+        This is the "lower half" of a matrix, in the sense that we
+        keep the strictly lower-triangular part, and keep half of the
+        diagonal (so that ``up_hat(x) + down_hat(x) == x``. It is
+        defined by Vinberg on page 381, and is used to construct a
+        clan whose associated cone equals that of the the T-algebra.
+        """
+        return MatrixClan._up_hat(x.transpose()).transpose()
+
+    @staticmethod
+    def _cp(x,y):
+        r"""
+        The clan product associated with a T-algebra.
+
+        This is defined by Vinberg on page 381 (as Delta), who then
+        proceeds to explain, over the course of the next few pages,
+        why it results in a clan when the we take the underlying set
+        to be the subspace of symmetric elements.
+
+        .. WARNING:
+
+            We use Ishi's version of this product that reverses
+            the indices.
+
+        """
+        # First we lift x,y out of the clan and into
+        # the general matrix space.
+        H = x.parent()
+        x = x.lift()
+        y = y.lift()
+
+        # Note: within a Hermitian matrix space we can't represent the
+        # (non-Hermitian) intermediate terms _down_hat(x) and _up_hat(x)!
+        return H(MatrixClan._down_hat(x)*y + y*MatrixClan._up_hat(x))
+
+    @staticmethod
+    def _ip(x,y):
+        r"""
+        The Ishi inner product (NOT the canonical one) on a clan.
+        """
+        two = x.base_ring()(2)
+        p = MatrixClan._cp(x,y) / two
+        return sum( p[idx]
+                    for idx in p.monomial_coefficients()
+                    if idx[0] == idx[1] )
+
     def from_matrix(self, x):
         r"""
         Construct an element of this clan from a Hermitian matrix.
@@ -347,62 +417,7 @@ class SnClan(MatrixClan):
                                 support_order=b.keys(),
                                 ambient=Mn)
 
-        def up_hat(x):
-            r"""
-            The "up-hat" function on a T-algebra.
-
-            This is the "top half" of a matrix, in the sense that we keep the
-            strictly upper-triangular part, and keep half of the diagonal (so
-            that ``up_hat(x) + down_hat(x) == x``. It is defined by Vinberg on
-            page 381, and is used to construct a clan whose associated cone
-            equals that of the the T-algebra.
-
-            """
-            def l(i,j):
-                if i < j:
-                    return x[i,j]
-                if i == j:
-                    return x[i,j]/scalar_field(2)
-                else:
-                    return 0
-            return Mn(l)
-
-        def down_hat(x):
-            r"""
-            The "down-hat" function on a T-algebra.
-
-            This is the "lower half" of a matrix, in the sense that we keep
-            the strictly lower-triangular part, and keep half of the diagonal
-            (so that ``up_hat(x) + down_hat(x) == x``. It is defined by
-            Vinberg on page 381, and is used to construct a clan whose
-            associated cone equals that of the the T-algebra.
-            """
-            return up_hat(x.T).T
-
-        def cp(x,y):
-            r"""
-            The clan product associated with a T-algebra.
-
-            This is defined by Vinberg on page 381 (as Delta), who
-            then proceeds to explain, over the course of the next few
-            pages, why it results in a clan when the we take the
-            underlying set to be the subspace of symmetric elements.
-
-            .. WARNING:
-
-                We use Ishi's version of this product that reverses
-                the indices.
-
-            """
-            x = x.lift()
-            y = y.lift()
-            return Sn(down_hat(x)*y + y*up_hat(x))
-
-        def ip(x,y):
-            p = cp(x,y) / scalar_field(2)
-            return sum( p[(i,i,1)] for i in range(n) )
-
-        super().__init__(Sn, cp, ip, **kwargs)
+        super().__init__(Sn, MatrixClan._cp, MatrixClan._ip, **kwargs)
 
 
     def __repr__(self) -> str:
@@ -504,28 +519,7 @@ class HnClan(MatrixClan):
                                 support_order=b.keys(),
                                 ambient=Mn)
 
-        def up_hat(x):
-            return Mn.sum_of_terms(
-              ((i,j,k), a*c)
-              for ((i,j,k),c) in x.items()
-              if i <= j
-              if (a := 1 - (i == j)/scalar_field(2))
-            )
-
-        def down_hat(x):
-            return up_hat(x.transpose()).transpose()
-
-        def cp(x,y):
-            x = x.lift()
-            y = y.lift()
-            return Hn(down_hat(x)*y + y*up_hat(x))
-
-        def ip(x,y):
-            p = cp(x,y) / scalar_field(2)
-            one = QQbar(1)  # weird indexing in Hurwitz matrix algebras
-            return sum( p[i,i,one] for i in range(n) )
-
-        super().__init__(Hn, cp, ip, **kwargs)
+        super().__init__(Hn, MatrixClan._cp, MatrixClan._ip, **kwargs)
 
 
     def __repr__(self) -> str: