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
+)
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)
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]
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
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()
::
- 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] ])
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()
┌────┬───┐
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]
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
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
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()
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
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]
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()
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
"""
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()
SETUP::
- sage: from mjo.clan.clan import SnClan
+ sage: from mjo.clan.clan import RealSymmetricClan
EXAMPLES:
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()
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()
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)
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]
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]
SETUP::
- sage: from mjo.clan.clan import SnClan, VinbergClan
+ sage: from mjo.clan.clan import RealSymmetricClan, VinbergClan
EXAMPLES:
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 )
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
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 )
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
SETUP::
- sage: from mjo.clan.clan import SnClan
+ sage: from mjo.clan.clan import RealSymmetricClan
sage: from mjo.clan.clan_operator import ClanOperator
EXAMPLES:
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)
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],
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()
[ 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():
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:
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
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:
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)