From d82f7b471a386f8f03e54a519b040a3b55c48fbf Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Fri, 23 Jan 2026 09:02:25 -0500 Subject: [PATCH] mjo/clan: WIP conversion to three coordinates --- mjo/clan/clan_element.py | 42 ++++++++++++++++++++++++---------------- mjo/clan/unital_clan.py | 23 +++++++++++----------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/mjo/clan/clan_element.py b/mjo/clan/clan_element.py index 30bf82a..4aba6d1 100644 --- a/mjo/clan/clan_element.py +++ b/mjo/clan/clan_element.py @@ -34,7 +34,7 @@ class ClanElement(IndexedFreeModuleElement): 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)]) ) + ....: if (e_ii := C.basis()[(i,i,1)]) ) True """ @@ -71,22 +71,27 @@ class NormalDecompositionElement(ClanElement): sage: C = SnClan(3) sage: x = C.an_element(); x - 2*B(0, 0) + 2*B(1, 0) + 3*B(1, 1) + 2*B(0, 0, 1) + 2*B(1, 0, 1) + 3*B(1, 1, 1) sage: x.tr() 5 """ r = self.parent().rank() - return sum( self[i,i] for i in range(r) ) + return sum( self[i,i,1] for i in range(r) ) - def elt(self, idx): + def elt(self, i, j): r""" - The algebra component of ``self`` at index ``idx``. + The algebra component of ``self`` at position ``i,j``. This is in contrast with the usual indexing that returns only a coefficient. + .. WARNING: + + This returns zero if you request a component that does + not exist (with ``i`` strictly less than ``j``). + SETUP:: sage: from mjo.clan.unital_clan import SnClan @@ -99,33 +104,36 @@ class NormalDecompositionElement(ClanElement): [ 2 6 10] [ 6 10 14] [10 14 18] - sage: X.elt( (0,0) ).lift().lift() + sage: X.elt(0,0).lift().lift() [2 0 0] [0 0 0] [0 0 0] - sage: X.elt( (1,0) ).lift().lift() + sage: X.elt(1,0).lift().lift() [0 6 0] [6 0 0] [0 0 0] - sage: X.elt( (1,1) ).lift().lift() + sage: X.elt(1,1).lift().lift() [ 0 0 0] [ 0 10 0] [ 0 0 0] - sage: X.elt( (2,0) ).lift().lift() + sage: X.elt(2,0).lift().lift() [ 0 0 10] [ 0 0 0] [10 0 0] - sage: X.elt( (2,1) ).lift().lift() + sage: X.elt(2,1).lift().lift() [ 0 0 0] [ 0 0 14] [ 0 14 0] - sage: X.elt( (2,2) ).lift().lift() + sage: X.elt(2,2).lift().lift() [ 0 0 0] [ 0 0 0] [ 0 0 18] """ - return self[idx]*self.parent().monomial(idx) + return sum( ( c*self.parent().monomial(idx) + for (idx,c) in self.items() + if (idx[0] == i and idx[1] == j) ), + self.parent().zero() ) def seq(self, i): @@ -179,19 +187,19 @@ class NormalDecompositionElement(ClanElement): for m in range(i, P.rank()): for k in range(i, m+1): - a = x_prev.elt( (m, i-1) ) - b = x_prev.elt( (k, i-1) ) + a = x_prev.elt(m, i-1) + b = x_prev.elt(k, i-1) - x_i += x_prev[i-1,i-1]*x_prev.elt( (m,k) ) + x_i += x_prev[i-1,i-1,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) ) + x_i -= a.inner_product(b) * P.monomial( (m,k,1) ) 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]. - x_i -= (a*b).elt( (m,k) ) + x_i -= (a*b).elt(m,k) return x_i diff --git a/mjo/clan/unital_clan.py b/mjo/clan/unital_clan.py index e0a0404..ab601be 100644 --- a/mjo/clan/unital_clan.py +++ b/mjo/clan/unital_clan.py @@ -154,27 +154,27 @@ class SnClan(NormalDecomposition): sage: n = 3 sage: C = SnClan(n) sage: e = C.basis() - sage: all( e[i,i]*e[i,i] == e[i,i] for i in range(n) ) + sage: all( e[i,i,1]*e[i,i,1] == e[i,i,1] for i in range(n) ) True - sage: all( e[i,i]*e[j,i] == e[j,i]/2 + sage: all( e[i,i,1]*e[j,i,1] == e[j,i,1]/2 ....: for i in range(n) ....: for j in range(i+1,n)) True - sage: all( e[i,i]*e[i,k] == e[i,k]/2 + sage: all( e[i,i,1]*e[i,k,1] == e[i,k,1]/2 ....: for i in range(n) ....: for k in range(i)) True - sage: all( (e[i,i]*e[j,k]).is_zero() + sage: all( (e[i,i,1]*e[j,k,1]).is_zero() ....: for i in range(n) ....: for j in range(n) ....: for k in range(j+1) ....: if not i in [j,k] ) True - sage: all( (e[i,k]*e[i,i]).is_zero() + sage: all( (e[i,k,1]*e[i,i,1]).is_zero() ....: for i in range(n) ....: for k in range(i) ) True - sage: all( (e[j,k]*e[i,i]).is_zero() + sage: all( (e[j,k,1]*e[i,i,1]).is_zero() ....: for i in range(n) ....: for j in range(n) ....: for k in range(j) @@ -186,7 +186,7 @@ class SnClan(NormalDecomposition): sage: C = SnClan(3) sage: x = C.an_element(); x - 2*B(0, 0) + 2*B(1, 0) + 3*B(1, 1) + 2*B(0, 0, 1) + 2*B(1, 0, 1) + 3*B(1, 1, 1) sage: x.lift().lift() [2 2 0] [2 3 0] @@ -199,7 +199,7 @@ class SnClan(NormalDecomposition): b = Mn.basis() from sage.sets.family import Family - Sn_basis = Family({ (i,j) : + Sn_basis = Family({ (i,j,1) : a*(b[(i,j)] + b[(j,i)]) for i in range(n) for j in range(i+1) @@ -265,7 +265,7 @@ class SnClan(NormalDecomposition): def ip(x,y): p = cp(x,y) / scalar_field(2) - return sum( p[(i,i)] for i in range(n) ) + return sum( p[(i,i,1)] for i in range(n) ) super().__init__(Sn, cp, ip, **kwargs) @@ -300,7 +300,7 @@ class SnClan(NormalDecomposition): True """ - return sum( self.basis()[i,i] for i in range(self.rank()) ) + return sum( self.basis()[i,i,1] for i in range(self.rank()) ) def from_matrix(self, x): @@ -323,7 +323,8 @@ class SnClan(NormalDecomposition): raise ValueError if not self.rank() == x.nrows(): raise ValueError - return self.sum_of_terms( (k, x[k]) for k in self.indices() ) + return self.sum_of_terms( ((i,j,k), x[i,j]) + for (i,j,k) in self.indices() ) def from_list(self, l): -- 2.51.0