"""
return f"Clan H^{self.rank()} over {self.base_ring()}"
+
class VinbergClan(NormalDecomposition):
r"""
The clan corresponding to the Vinberg cone (as defined by Ishi).
real numbers, and provide lifts to the matrix representation. The
clan product is in terms of the up-hat and down-hat that is
defined on `S^{2}.
+
+ Following Gikdikin (p. 91), the basis for this clan is
+
+ e[(0,0,1)] = [1,0], [1,0]
+ [0,0] [0,0]
+
+ e[(1,0,1)] = [0,1], [0,0]
+ [1,0] [0,0]
+
+ e[(1,1,1)] = [0,0], [0,0]
+ [0,1] [0,0]
+
+ e[(2,0,1)] = [0,0], [0,1]
+ [0,0] [1,0]
+
+ e[(2,1,1)] = nonexistent, component is trivial
+
+ e[(2,2,1)] = [0,0], [0,0]
+ [0,0] [0,1]
+
+ Check the unit element::
+
+ sage: C = VinbergClan()
+ sage: x = C.an_element()
+ sage: x*C.one() == x
+ True
+ sage: C.one()*x == x
+ True
+
+ Verifying the axioms::
+
+ sage: C = VinbergClan()
+ sage: e = C.basis()
+ sage: all( e[i,i,1]*e[i,i,1] == e[i,i,1] for i in range(3) )
+ True
+ sage: all( e[i,i,1]*e[j,i,1] == e[j,i,1]/2
+ ....: for i in range(3)
+ ....: for j in range(i+1,3)
+ ....: if e.has_key((j,i,1)))
+ True
+ sage: all( e[i,i,1]*e[i,k,1] == e[i,k,1]/2
+ ....: for i in range(2)
+ ....: for k in range(i))
+ True
+ sage: all( (e[i,i,1]*e[j,k,1]).is_zero()
+ ....: for i in range(2)
+ ....: for j in range(2)
+ ....: for k in range(j+1)
+ ....: if not i in [j,k] )
+ True
+ sage: all( (e[i,k,1]*e[i,i,1]).is_zero()
+ ....: for i in range(2)
+ ....: for k in range(i) )
+ True
+ sage: all( (e[j,k,1]*e[i,i,1]).is_zero()
+ ....: for i in range(2)
+ ....: for j in range(2)
+ ....: for k in range(j)
+ ....: if not i in [j,k] )
+ True
+
"""
def __init__(self, scalar_field=QQ, **kwargs):
from sage.matrix.matrix_space import MatrixSpace
ambient=M2)
# We need an Ishi basis (i,j,k) for R^5 if we want to use
- # NormalDecomposition.
+ # NormalDecomposition. We imagine the (2,1,1) component
+ # being trivial to keep the "triangle" intact. We are
+ # example (f) on page 91 of Gindikin where we can cheat
+ # and see the normal decomposition.
R5 = VectorSpace(scalar_field, [
(0,0,1),
(1,0,1),
(1,1,1),
- (2,1,1),
+ (2,0,1),
(2,2,1)
])
return ( A[(0,0,1)]*R5((0,0,1)) +
A[(1,0,1)]*R5((1,0,1)) +
A[(1,1,1)]*R5((1,1,1)) +
- B[(1,0,1)]*R5((2,1,1)) +
+ B[(1,0,1)]*R5((2,0,1)) +
B[(1,1,1)]*R5((2,2,1)) )
def lift(v):
self._S2((1,0,1))*v[(1,0,1)] +
self._S2((1,1,1))*v[(1,1,1)] )
M2 = ( self._S2((0,0,1))*v[(0,0,1)] +
- self._S2((1,0,1))*v[(2,1,1)] +
+ self._S2((1,0,1))*v[(2,0,1)] +
self._S2((1,1,1))*v[(2,2,1)] )
return (M1,M2)
def cp(x,y):
+ # up_hat and down_hat need MatrixSpace elements, not
+ # submodules with custom bases, so we need to lift
+ # everything twice.
X1,X2 = lift(x)
Y1,Y2 = lift(y)
+ X1 = X1.lift()
+ X2 = X2.lift()
+ Y1 = Y1.lift()
+ Y2 = Y2.lift()
Z1 = MatrixClan._down_hat(X1)*Y1 + Y1*MatrixClan._up_hat(X1)
Z2 = MatrixClan._down_hat(X2)*Y2 + Y2*MatrixClan._up_hat(X2)
- return unlift(Z1,Z2)
+ return unlift((self._S2(Z1), self._S2(Z2)))
def ip(x,y):
two = x.base_ring()(2)