From: Michael Orlitzky Date: Sat, 24 Jan 2026 02:15:57 +0000 (-0500) Subject: mjo/clan: new diag() method for elements, everything now index-agnostic X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=b69d64c2eec2e0ad1450e6a3bc268d83f15503d0;p=sage.d.git mjo/clan: new diag() method for elements, everything now index-agnostic With idempotent() and diag() helpers, the element code now does not need to know what the indexing scheme is. --- diff --git a/mjo/clan/clan_element.py b/mjo/clan/clan_element.py index 6383703..bd481ea 100644 --- a/mjo/clan/clan_element.py +++ b/mjo/clan/clan_element.py @@ -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):