From 7e79d6d31cf52cc5b0c2119781b343b00ac351d9 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Sun, 22 Feb 2026 11:34:24 -0500 Subject: [PATCH] mjo/clan: rename SnClan and HnClan for consistency with EJA names --- mjo/clan/all.py | 7 ++++- mjo/clan/clan.py | 54 ++++++++++++++++++++------------------- mjo/clan/clan_element.py | 38 +++++++++++++-------------- mjo/clan/clan_operator.py | 37 +++++++++++++++------------ 4 files changed, 73 insertions(+), 63 deletions(-) diff --git a/mjo/clan/all.py b/mjo/clan/all.py index ffc0677..3467745 100644 --- a/mjo/clan/all.py +++ b/mjo/clan/all.py @@ -1,4 +1,9 @@ r""" All user-facing imports from mjo.clan. """ -from mjo.clan.clan import Clans, HnClan, SnClan, VinbergClan +from mjo.clan.clan import ( + Clans, + ComplexHermitianClan, + RealSymmetricClan, + VinbergClan +) diff --git a/mjo/clan/clan.py b/mjo/clan/clan.py index 017c2c8..4838360 100644 --- a/mjo/clan/clan.py +++ b/mjo/clan/clan.py @@ -193,11 +193,11 @@ class NormalDecomposition(UnitalClan): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: C.idempotent(0) B(0, 0, 1) sage: C.idempotent(1) @@ -218,11 +218,11 @@ class NormalDecomposition(UnitalClan): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(4) + sage: C = RealSymmetricClan(4) sage: I = C.one() sage: I.lift().lift() [1 0 0 0] @@ -248,11 +248,11 @@ class NormalDecomposition(UnitalClan): SETUP:: - sage: from mjo.clan.clan import HnClan + sage: from mjo.clan.clan import ComplexHermitianClan EXAMPLES:: - sage: C = HnClan(2) + sage: C = ComplexHermitianClan(2) sage: C.rank() 2 @@ -340,12 +340,13 @@ class MatrixClan(NormalDecomposition): SETUP:: - sage: from mjo.clan.clan import HnClan, SnClan + sage: from mjo.clan.clan import ( ComplexHermitianClan, + ....: RealSymmetricClan ) sage: from mjo.hurwitz import ComplexMatrixAlgebra EXAMPLES:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: X = matrix(QQ, [[2,1], ....: [1,4]]) sage: C.from_matrix(X).lift().lift() @@ -354,7 +355,7 @@ class MatrixClan(NormalDecomposition): :: - sage: C = HnClan(2) + sage: C = ComplexHermitianClan(2) sage: A = ComplexMatrixAlgebra(2, QQbar, QQ) sage: X = A([ [ 2, 1 + 2*I], ....: [ 1 - 2*I, -1] ]) @@ -395,11 +396,12 @@ class MatrixClan(NormalDecomposition): SETUP:: - sage: from mjo.clan.clan import HnClan, SnClan + sage: from mjo.clan.clan import ( ComplexHermitianClan, + ....: RealSymmetricClan ) EXAMPLES:: - sage: C = HnClan(2) + sage: C = ComplexHermitianClan(2) sage: X = C.from_list([[0,I],[-I,0]]) sage: X.lift().lift() ┌────┬───┐ @@ -412,7 +414,7 @@ class MatrixClan(NormalDecomposition): matrix, so in the real case, we can use one long list (as opposed to a list of lists): - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = C.from_list([2,6,10,6,10,14,10,14,18]) sage: X.lift().lift() [ 2 6 10] @@ -423,7 +425,7 @@ class MatrixClan(NormalDecomposition): return self.from_matrix(self._vector_space.ambient()(l)) -class SnClan(MatrixClan): +class RealSymmetricClan(MatrixClan): r""" The normally-decomposed clan of real symmetric matrices of a given size with the clan product and lower-triangular basis @@ -432,21 +434,21 @@ class SnClan(MatrixClan): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES: The rank of this clan is the size of the matrices:: sage: n = ZZ.random_element(1,5) - sage: C = SnClan(n) + sage: C = RealSymmetricClan(n) sage: C.rank() == n True Verifying the axioms:: sage: n = 3 - sage: C = SnClan(n) + sage: C = RealSymmetricClan(n) sage: e = C.basis() sage: all( e[i,i,1]*e[i,i,1] == e[i,i,1] for i in range(n) ) True @@ -478,7 +480,7 @@ class SnClan(MatrixClan): With a little effort, we can lift elements of the clan back into the original (asymmetric) matrix space:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: x = C.an_element(); x 2*B(0, 0, 1) + 2*B(1, 0, 1) + 3*B(1, 1, 1) sage: x.lift().lift() @@ -515,18 +517,18 @@ class SnClan(MatrixClan): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: SnClan(5) + sage: RealSymmetricClan(5) Clan S^5 over Rational Field """ return f"Clan S^{self.rank()} over {self.base_ring()}" -class HnClan(MatrixClan): +class ComplexHermitianClan(MatrixClan): r""" The normally-decomposed clan of complex Hermitian matrices of a given size with the clan product and lower-triangular basis @@ -535,21 +537,21 @@ class HnClan(MatrixClan): SETUP:: - sage: from mjo.clan.clan import HnClan + sage: from mjo.clan.clan import ComplexHermitianClan EXAMPLES: The rank of this clan is the size of the matrices:: sage: n = ZZ.random_element(1,5) - sage: C = HnClan(n) + sage: C = ComplexHermitianClan(n) sage: C.rank() == n True Verifying the axioms:: sage: n = 3 - sage: C = HnClan(n) + sage: C = ComplexHermitianClan(n) sage: e = C.basis() sage: r = C.rank() sage: all( e[i,j,k]*e[i,j,k] == e[i,j,k] @@ -582,7 +584,7 @@ class HnClan(MatrixClan): With a little effort, we can lift elements of the clan back into the original (asymmetric) matrix space:: - sage: C = HnClan(3) + sage: C = ComplexHermitianClan(3) sage: x = C.an_element(); x 2*B(0, 0, 1) + 3*B(1, 0, I) + 2*B(1, 0, 1) sage: x.lift().lift() @@ -625,11 +627,11 @@ class HnClan(MatrixClan): SETUP:: - sage: from mjo.clan.clan import HnClan + sage: from mjo.clan.clan import ComplexHermitianClan EXAMPLES:: - sage: HnClan(1) + sage: ComplexHermitianClan(1) Clan H^1 over Rational Field """ diff --git a/mjo/clan/clan_element.py b/mjo/clan/clan_element.py index f4869a2..1cf73a3 100644 --- a/mjo/clan/clan_element.py +++ b/mjo/clan/clan_element.py @@ -24,14 +24,14 @@ class ClanElement(IndexedFreeModuleElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES: In the clan of real symmetric matrices under the Ishi norm, it is easy to check that the idempotents all have norm 1/2:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) 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() @@ -54,7 +54,7 @@ class ClanElement(IndexedFreeModuleElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES: @@ -62,7 +62,7 @@ class ClanElement(IndexedFreeModuleElement): it follows that for a symmetric matrix this is twice the usual trace:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = matrix(QQ, [[2,6,10],[6,10,14],[10,14,18]]) sage: Y = matrix(QQ, [[2,1,0],[1,1,1],[0,1,4]]) sage: (X*Y).trace() @@ -155,17 +155,17 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(4) + sage: C = RealSymmetricClan(4) sage: C.one().tr() 4 :: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: x = C.an_element(); x 2*B(0, 0, 1) + 2*B(1, 0, 1) + 3*B(1, 1, 1) sage: x.tr() @@ -188,11 +188,11 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(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) @@ -233,11 +233,11 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = C.from_list([2,6,10,6,10,14,10,14,18]) sage: X.lift().lift() [ 2 6 10] @@ -284,13 +284,13 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES: The base case is trivial:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = C.from_list([2,6,10,6,10,14,10,14,18]) sage: X.lift().lift() [ 2 6 10] @@ -351,7 +351,7 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan, VinbergClan + sage: from mjo.clan.clan import RealSymmetricClan, VinbergClan EXAMPLES: @@ -359,7 +359,7 @@ class NormalDecompositionElement(ClanElement): stabilizes the identity, even in simple cases, because the first polynomial refers to exactly one diagonal coordinate:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: X = C.from_list([[2,1],[1,4]]) sage: P = matrix(QQ, [[0,1],[1,0]]) sage: phi = lambda X: C.from_matrix( P*X.lift().lift()*P.T ) @@ -370,7 +370,7 @@ class NormalDecompositionElement(ClanElement): Even the composite determinant need not be preserved:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = matrix(QQ, [[2,1,0],[1,1,1],[0,1,4]]) sage: X.is_positive_semidefinite() True @@ -413,14 +413,14 @@ class NormalDecompositionElement(ClanElement): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES: These are not preserved by cone automorphisms that fix the identity, even in the usual Cholesky decomposition:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: X = C.from_list([[2,1],[1,4]]) sage: P = matrix(QQ, [[0,1],[1,0]]) sage: phi = lambda X: C.from_matrix( P*X.lift().lift()*P.T ) @@ -441,7 +441,7 @@ class NormalDecompositionElement(ClanElement): But their product *is* preserved if the cone is symmetric:: - sage: C = SnClan(3) + sage: C = RealSymmetricClan(3) sage: X = matrix(QQ, [[2,1,0],[1,1,1],[0,1,4]]) sage: X.is_positive_semidefinite() True diff --git a/mjo/clan/clan_operator.py b/mjo/clan/clan_operator.py index 9f689e5..a85c7e1 100644 --- a/mjo/clan/clan_operator.py +++ b/mjo/clan/clan_operator.py @@ -8,7 +8,7 @@ class ClanOperator(Map): SETUP:: - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan sage: from mjo.clan.clan_operator import ClanOperator EXAMPLES: @@ -16,7 +16,7 @@ class ClanOperator(Map): The domain and codomain must be clans; if either is not, then an error is raised:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: V = VectorSpace(C.base_ring(), 3) sage: M = matrix.identity(C.base_ring(), 3) sage: ClanOperator(V,C,M) @@ -94,13 +94,15 @@ class ClanOperator(Map): SETUP:: sage: from mjo.clan.clan_operator import ClanOperator - sage: from mjo.clan.clan import HnClan, SnClan, VinbergClan + sage: from mjo.clan.clan import ( ComplexHermitianClan, + ....: RealSymmetricClan, + ....: VinbergClan ) EXAMPLES:: sage: C1 = VinbergClan() - sage: C2 = HnClan(2) - sage: C3 = SnClan(2) + sage: C2 = ComplexHermitianClan(2) + sage: C3 = RealSymmetricClan(2) sage: mat1 = matrix(QQ, [[1,2,3,4,5], ....: [6,7,8,9,0], ....: [1,2,3,4,5], @@ -135,14 +137,15 @@ class ClanOperator(Map): SETUP:: - sage: from mjo.clan.clan import HnClan + sage: from mjo.clan.clan import ComplexHermitianClan sage: from mjo.clan.clan_operator import ClanOperator EXAMPLES: - We can scale an operator on a rational algebra by a rational number:: + We can scale an operator on a rational algebra by a rational + number:: - sage: C = HnClan(2) + sage: C = ComplexHermitianClan(2) sage: b0,b1,b2,b3 = C.gens() sage: x = 4*b0 + 8*b1 + 32*b2 + 64*b3 sage: x.operator() @@ -161,7 +164,6 @@ class ClanOperator(Map): [ 0 8 32 32] Domain: Clan H^2 over Rational Field Codomain: Clan H^2 over Rational Field - """ try: if other in self.codomain().base_ring(): @@ -185,11 +187,12 @@ class ClanOperator(Map): SETUP:: sage: from mjo.clan.clan_operator import ClanOperator - sage: from mjo.clan.clan import HnClan, SnClan + sage: from mjo.clan.clan import ( ComplexHermitianClan, + ....: RealSymmetricClan ) EXAMPLES:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: f = C.random_element().operator() sage: f^0 Clan operator represented by the matrix: @@ -212,8 +215,8 @@ class ClanOperator(Map): Exponentiation doesn't work when the domain and codomain differ, even if their dimensions are compatible:: - sage: C1 = SnClan(1) - sage: C2 = HnClan(1) + sage: C1 = RealSymmetricClan(1) + sage: C2 = ComplexHermitianClan(1) sage: I = C1.one().operator().matrix() sage: L = ClanOperator(C1, C2, I) sage: L^2 @@ -246,11 +249,11 @@ class ClanOperator(Map): SETUP:: sage: from mjo.clan.clan_operator import ClanOperator - sage: from mjo.clan.clan import HnClan + sage: from mjo.clan.clan import ComplexHermitianClan EXAMPLES:: - sage: C = HnClan(2) + sage: C = ComplexHermitianClan(2) sage: id = identity_matrix(C.base_ring(), C.dimension()) sage: ClanOperator(C,C,id) Clan operator represented by the matrix: @@ -277,11 +280,11 @@ class ClanOperator(Map): SETUP:: sage: from mjo.clan.clan_operator import ClanOperator - sage: from mjo.clan.clan import SnClan + sage: from mjo.clan.clan import RealSymmetricClan EXAMPLES:: - sage: C = SnClan(2) + sage: C = RealSymmetricClan(2) sage: d = C.dimension() sage: mat = matrix(C.base_ring(), d, range(d**2)) sage: f = ClanOperator(C,C,mat) -- 2.51.0