]> gitweb.michael.orlitzky.com - sage.d.git/commitdiff
mjo/clan: new diag() method for elements, everything now index-agnostic
authorMichael Orlitzky <michael@orlitzky.com>
Sat, 24 Jan 2026 02:15:57 +0000 (21:15 -0500)
committerMichael Orlitzky <michael@orlitzky.com>
Sat, 24 Jan 2026 02:15:57 +0000 (21:15 -0500)
With idempotent() and diag() helpers, the element code now does not
need to know what the indexing scheme is.

mjo/clan/clan_element.py

index 6383703007124409be82e930d1d850bfe52faa39..bd481eaa3ba63d66f0e64e5c9e4db52604779ba6 100644 (file)
@@ -32,9 +32,10 @@ class ClanElement(IndexedFreeModuleElement):
         it is easy to check that the idempotents all have norm 1/2::
 
             sage: C = SnClan(3)
-            sage: all( e_ii.inner_product(e_ii) == 1/2
-            ....:      for i in range(C.rank())
-            ....:      if (e_ii := C.basis()[(i,i,1)]) )
+            sage: b = C.basis()
+            sage: all( b[i,j,k].inner_product(b[i,j,k]) == 1/2
+            ....:      for (i,j,k) in b.keys()
+            ....:      if j == i )
             True
 
         """
@@ -79,9 +80,52 @@ class NormalDecompositionElement(ClanElement):
             sage: x.tr()
             5
 
+        """
+        return self.base_ring().sum(
+            self[i,j,k]
+            for (i,j,k) in self.monomial_coefficients()
+            if j == i
+        )
+
+
+    def diag(self, i):
+        r"""
+        Return the i'th diagonal coordinate of this element.
+
+        This is a shortcut for `x[i,i,k]` that does not require
+        knowledge of the indexing scheme in the third component.
+
+        SETUP::
+
+            sage: from mjo.clan.unital_clan import SnClan
+
+        EXAMPLES::
+
+            sage: C = SnClan(3)
+            sage: x = C.an_element(); x
+            2*B(0, 0, 1) + 2*B(1, 0, 1) + 3*B(1, 1, 1)
+            sage: x.diag(0)
+            2
+            sage: x.diag(1)
+            3
+            sage: x.diag(2)
+            0
+            sage: x.diag(3)
+            Traceback (most recent call last):
+            ...
+            IndexError: index i=3 invalid in rank=3
+
         """
         r = self.parent().rank()
-        return sum( self[i,i,1] for i in range(r) )
+        if i >= r:
+            raise IndexError(f"index i={i} invalid in rank={r}")
+
+        return self.base_ring().sum(
+            self[j,k,l]
+            for (j,k,l) in self.monomial_coefficients()
+            if  j == i
+            and k == i
+        )
 
 
     def elt(self, i, j):
@@ -134,10 +178,11 @@ class NormalDecompositionElement(ClanElement):
             [ 0  0 18]
 
         """
-        return sum( ( c*self.parent().monomial(idx)
-                      for (idx,c) in self.items()
-                      if (idx[0] == i and idx[1] == j) ),
-                    self.parent().zero() )
+        return self.parent().sum_of_terms(
+            item
+            for item in self.items()
+            if item[0][0] == i and item[0][1] == j
+        )
 
 
     def seq(self, i):
@@ -194,12 +239,12 @@ class NormalDecompositionElement(ClanElement):
                 a = x_prev.elt(m, i-1)
                 b = x_prev.elt(k, i-1)
 
-                x_i += x_prev[i-1,i-1,1]*x_prev.elt(m,k)
+                x_i += x_prev.diag(i-1)*x_prev.elt(m,k)
 
                 if k == m:
                     # A special case is needed only for the factor of
                     # two in the inner product.
-                    x_i -= a.inner_product(b) * P.monomial( (m,k,1) )
+                    x_i -= a.inner_product(b) * P.idempotent(m)
                 else:
                     # [m,i]*[k,i] is contained in either [m,k] or [k,m],
                     # whichever makes sense. We've got m>k, so use [m,k].
@@ -247,7 +292,9 @@ class NormalDecompositionElement(ClanElement):
             8
 
         """
-        return self.seq(k)[k,k,1]
+        # The sum() hijinks avoid needing to know what the third
+        # coordinate is.
+        return self.seq(k).diag(k)
 
 
     def chi(self, k):