Skip to content

Commit e47b1c5

Browse files
committed
Extending the implementation to any finite dimensional representation.
1 parent 7063baf commit e47b1c5

File tree

4 files changed

+223
-72
lines changed

4 files changed

+223
-72
lines changed

src/sage/algebras/lie_algebras/lie_algebra_element.pyx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element):
12321232
return type(self)(self._parent, negate(self._t_dict),
12331233
-self._c_coeff, -self._d_coeff)
12341234

1235-
cpdef _acted_upon_(self, x, bint self_on_left) noexcept:
1235+
cpdef _acted_upon_(self, scalar, bint self_on_left) noexcept:
12361236
"""
12371237
Return ``self`` acted upon by ``x``.
12381238
@@ -1246,9 +1246,21 @@ cdef class UntwistedAffineLieAlgebraElement(Element):
12461246
sage: -2 * x
12471247
(-2*E[alpha[1]])#t^0 + (-2*h1)#t^-1 + -6*c + 4/5*d
12481248
"""
1249-
return type(self)(self._parent, scal(x, self._t_dict, self_on_left),
1250-
x * self._c_coeff,
1251-
x * self._d_coeff)
1249+
# This was copied and IDK if it still applies (TCS):
1250+
# With the current design, the coercion model does not have
1251+
# enough information to detect apriori that this method only
1252+
# accepts scalars; so it tries on some elements(), and we need
1253+
# to make sure to report an error.
1254+
scalar_parent = parent(scalar)
1255+
if scalar_parent != self._parent.base_ring():
1256+
# Temporary needed by coercion (see Polynomial/FractionField tests).
1257+
if self._parent.base_ring().has_coerce_map_from(scalar_parent):
1258+
scalar = self._parent.base_ring()(scalar)
1259+
else:
1260+
return None
1261+
return type(self)(self._parent, scal(scalar, self._t_dict, self_on_left),
1262+
scalar * self._c_coeff,
1263+
scalar * self._d_coeff)
12521264

12531265
cpdef monomial_coefficients(self, bint copy=True) noexcept:
12541266
"""

src/sage/algebras/lie_algebras/representation.py

Lines changed: 161 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# https://www.gnu.org/licenses/
1717
# ****************************************************************************
1818

19-
from sage.sets.family import Family
19+
from sage.sets.family import Family, AbstractFamily
2020
from sage.combinat.free_module import CombinatorialFreeModule
2121
from sage.categories.modules import Modules
2222
from copy import copy
@@ -103,23 +103,75 @@ class RepresentationByMorphism(CombinatorialFreeModule, Representation_abstract)
103103
104104
- ``lie_algebra`` -- a Lie algebra
105105
- ``f`` -- the Lie algebra morphism defining the action of the basis
106-
elements of ``lie_algebra`` encoded as a ``dict`` with keys being
107-
indices of the basis of ``lie_algebra`` and the values being the
108-
corresponding matrix defining the action
106+
elements of ``lie_algebra``
107+
- ``index_set`` -- (optional) the index set of the module basis
108+
- ``on_basis`` -- (default: ``False``) the function ``f`` defines a
109+
map from the basis elements or from a generic element of ``lie_algebra``
110+
111+
If ``f`` is encoded as a ``dict`` or ``Family``, then the keys must
112+
be indices of the basis of ``lie_algebra`` and the values being the
113+
corresponding matrix defining the action. This sets ``on_basis=True``.
109114
110115
EXAMPLES::
111116
112117
sage: L.<x,y> = LieAlgebra(QQ, {('x','y'): {'y':1}})
113-
sage: f = ({x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])})
118+
sage: f = {x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])}
114119
sage: L.representation(f)
115120
Representation of Lie algebra on 2 generators (x, y) over Rational Field defined by:
116121
[1 0]
117122
x |--> [0 0]
118123
[0 1]
119124
y |--> [0 0]
125+
126+
We construct the direct sum of two copies of the trivial representation
127+
for an infinite dimensional Lie algebra::
128+
129+
sage: L = lie_algebras.Affine(QQ, ['E',6,1])
130+
sage: R = L.representation(lambda b: matrix.zero(QQ, 2), index_set=['a','b'])
131+
sage: x = L.an_element()
132+
sage: v = R.an_element(); v
133+
2*R['a'] + 2*R['b']
134+
sage: x * v
135+
0
136+
137+
We construct a finite dimensional representation of the affline Lie algebra
138+
of type `A_2^{(1)}`::
139+
140+
sage: L = lie_algebras.Affine(QQ, ['A',2,1]).derived_subalgebra()
141+
sage: Phi_plus = list(RootSystem(['A',2]).root_lattice().positive_roots())
142+
sage: def aff_action(key):
143+
....: mat = matrix.zero(QQ, 3)
144+
....: if key == 'c': # central element
145+
....: return mat
146+
....: b, ell = key
147+
....: if b in Phi_plus: # positive root
148+
....: ind = tuple(sorted(b.to_ambient().support()))
149+
....: mat[ind] = 1
150+
....: if ind[0] + 1 != ind[1]:
151+
....: mat[ind] = -1
152+
....: elif -b in Phi_plus: # negative root
153+
....: ind = tuple(sorted(b.to_ambient().support(), reverse=True))
154+
....: mat[ind] = 1
155+
....: if ind[0] - 1 != ind[1]:
156+
....: mat[ind] = -1
157+
....: else: # must be in the Cartan
158+
....: i = b.leading_support()
159+
....: mat[i,i] = -1
160+
....: mat[i-1,i-1] = 1
161+
....: return mat
162+
sage: F = Family(L.basis(), aff_action, name="lifted natural repr")
163+
sage: R = L.representation(index_set=range(1,4), on_basis=F)
164+
sage: x = L.an_element(); x
165+
(E[alpha[2]] + E[alpha[1]] + h1 + h2 + E[-alpha[2]] + E[-alpha[1]])#t^0
166+
+ (E[-alpha[1] - alpha[2]])#t^1 + (E[alpha[1] + alpha[2]])#t^-1 + c
167+
sage: v = R.an_element(); v
168+
2*R[1] + 2*R[2] + 3*R[3]
169+
sage: x * v
170+
R[1] + 5*R[2] - 3*R[3]
171+
sage: R._test_representation() # verify that it is a representation
120172
"""
121173
@staticmethod
122-
def __classcall_private__(cls, lie_algebra, f, **kwargs):
174+
def __classcall_private__(cls, lie_algebra, f=None, index_set=None, on_basis=False, **kwargs):
123175
r"""
124176
Normalize inpute to ensure a unique representation.
125177
@@ -128,24 +180,69 @@ def __classcall_private__(cls, lie_algebra, f, **kwargs):
128180
sage: L.<x,y> = LieAlgebra(QQ, {('x','y'): {'y':1}})
129181
sage: f1 = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0,1],[0,0]])}
130182
sage: R1 = L.representation(f1)
131-
sage: f2 = Family({x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])})
183+
sage: f2 = Family({x: Matrix([[1,0],[0,0]]), y: Matrix(QQ, [[0,1],[0,0]])})
132184
sage: R2 = L.representation(f2)
133185
sage: R1 is R2
134186
True
187+
188+
TESTS::
189+
190+
sage: L.<x,y> = LieAlgebra(QQ, {('x','y'): {'y':1}})
191+
sage: f = {'x': Matrix([[1,0]]), 'y': Matrix([[0,1]])}
192+
sage: R = L.representation(f)
193+
Traceback (most recent call last):
194+
...
195+
ValueError: all matrices must be square
196+
197+
sage: f = {'x': Matrix([[1,0],[0,0]]), 'y': Matrix([[0]])}
198+
sage: R = L.representation(f)
199+
Traceback (most recent call last):
200+
...
201+
ValueError: all matrices must be square of size 2
135202
"""
136-
C = Modules(lie_algebra.base_ring()).WithBasis().FiniteDimensional()
203+
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
204+
base = lie_algebra.base_ring()
205+
C = Modules(base).WithBasis().FiniteDimensional()
137206
C = C.or_subcategory(kwargs.pop('category', C))
138207
B = lie_algebra.basis()
139-
data = {}
140-
for k, mat in f.items():
141-
if k in B:
142-
k = k.leading_support()
143-
data[k] = copy(mat)
144-
data[k].set_immutable()
145-
f = Family(data)
146-
return super(cls, RepresentationByMorphism).__classcall__(cls, lie_algebra, f, category=C, **kwargs)
147-
148-
def __init__(self, lie_algebra, f, category, **kwargs):
208+
if not isinstance(on_basis, bool):
209+
f = on_basis
210+
on_basis = True
211+
if isinstance(f, AbstractFamily):
212+
if f.cardinality() < float('inf'):
213+
f = dict(f)
214+
on_basis = True
215+
if isinstance(f, dict):
216+
data = {}
217+
dim = None
218+
for k, mat in f.items():
219+
if k in B:
220+
k = k.leading_support()
221+
if not mat.is_square():
222+
raise ValueError("all matrices must be square")
223+
if dim is None:
224+
dim = mat.nrows()
225+
elif mat.nrows() != dim or mat.ncols() != dim:
226+
raise ValueError("all matrices must be square of size {}".format(dim))
227+
data[k] = mat.change_ring(base)
228+
data[k].set_immutable()
229+
230+
if index_set is None:
231+
index_set = FiniteEnumeratedSet(range(dim))
232+
f = Family(data)
233+
on_basis = True
234+
235+
if f is None:
236+
raise ValueError("either 'f' or 'on_basis' must be specified")
237+
if index_set is None:
238+
raise ValueError("the index set needs to be specified")
239+
240+
index_set = FiniteEnumeratedSet(index_set)
241+
242+
return super(cls, RepresentationByMorphism).__classcall__(cls, lie_algebra,
243+
f, index_set, on_basis, category=C, **kwargs)
244+
245+
def __init__(self, lie_algebra, f, index_set, on_basis, category, **kwargs):
149246
r"""
150247
Initialize ``self``.
151248
@@ -156,20 +253,17 @@ def __init__(self, lie_algebra, f, category, **kwargs):
156253
sage: R = L.representation(f)
157254
sage: TestSuite(R).run()
158255
"""
159-
it = iter(f)
160-
mat = next(it)
161-
if not mat.is_square():
162-
raise ValueError("all matrices must be square")
163-
dim = mat.nrows()
164-
self._mat_space = mat.parent()
165-
from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
166-
if any(mat.nrows() != dim or mat.ncols() != dim for mat in it):
167-
raise ValueError("all matrices must be square of size {}".format(dim))
168-
self._f = dict(f)
256+
if on_basis:
257+
self._family = f
258+
self._f = f.__getitem__
259+
else:
260+
self._f = f
261+
prefix = kwargs.pop("prefix", 'R')
262+
self._on_basis = on_basis
169263

170-
I = FiniteEnumeratedSet(range(dim))
171264
Representation_abstract.__init__(self, lie_algebra)
172-
CombinatorialFreeModule.__init__(self, lie_algebra.base_ring(), I, prefix='R', category=category)
265+
CombinatorialFreeModule.__init__(self, lie_algebra.base_ring(), index_set,
266+
category=category, prefix=prefix, **kwargs)
173267

174268
def _repr_(self):
175269
r"""
@@ -185,12 +279,28 @@ def _repr_(self):
185279
x |--> [0 0]
186280
[0 1]
187281
y |--> [0 0]
282+
283+
sage: L = lie_algebras.Affine(QQ, ['E',6,1])
284+
sage: F = Family(L.basis(), lambda b: matrix.zero(QQ, 2), name="zero map")
285+
sage: L.representation(F, index_set=['a','b'], on_basis=True)
286+
Representation of Affine Kac-Moody algebra of ['E', 6] in the Chevalley basis defined by:
287+
Lazy family (zero map(i))_{i in Lazy family...}
288+
289+
sage: L.representation(lambda b: matrix.zero(QQ, 2), index_set=['a','b'])
290+
Representation of Affine Kac-Moody algebra of ['E', 6] in the Chevalley basis defined by:
291+
<function <lambda> at 0x...>
188292
"""
189293
ret = "Representation of {} defined by:".format(self._lie_algebra)
190294
from sage.typeset.ascii_art import ascii_art
191-
B = self._lie_algebra.basis()
192-
for k in self._f:
193-
ret += '\n' + repr(ascii_art(B[k], self._f[k], sep=" |--> ", sep_baseline=0))
295+
if self._on_basis:
296+
B = self._lie_algebra.basis()
297+
if B.cardinality() < float('inf'):
298+
for k in B.keys():
299+
ret += '\n' + repr(ascii_art(B[k], self._f(k), sep=" |--> ", sep_baseline=0))
300+
else:
301+
ret += '\n' + repr(self._family)
302+
else:
303+
ret += '\n' + repr(self._f)
194304
return ret
195305

196306
class Element(CombinatorialFreeModule.Element):
@@ -220,14 +330,28 @@ def _acted_upon_(self, scalar, self_on_left=False):
220330
4*R[0] + 5*R[1]
221331
sage: (1/3*x - 5*y) * v
222332
-71/3*R[0]
333+
334+
sage: L = lie_algebras.Affine(QQ, ['E',6,1])
335+
sage: F = Family(L.basis(), lambda b: matrix.zero(QQ, 2), name="zero map")
336+
sage: R = L.representation(F, index_set=['a','b'], on_basis=True)
337+
sage: R.an_element()
338+
2*R['a'] + 2*R['b']
339+
sage: L.an_element() * R.an_element()
340+
0
223341
"""
224342
P = self.parent()
225343
if scalar in P._lie_algebra:
226344
if self_on_left:
227345
return None
346+
if not self: # we are (already) the zero vector
347+
return self
228348
scalar = P._lie_algebra(scalar)
229-
f = P._f
230-
mat = P._mat_space.sum(scalar[k] * f[k] for k in f if scalar[k])
349+
if not scalar: # we are acting by zero
350+
return P.zero()
351+
if P._on_basis:
352+
mat = sum(c * P._f(k) for k, c in scalar.monomial_coefficients(copy=False).items())
353+
else:
354+
mat = P._f(scalar)
231355
return P.from_vector(mat * self.to_vector())
232356

233357
return super()._acted_upon_(scalar, self_on_left)
@@ -249,7 +373,7 @@ class TrivialRepresentation(CombinatorialFreeModule, Representation_abstract):
249373
250374
- :wikipedia:`Trivial_representation`
251375
"""
252-
def __init__(self, lie_algebra):
376+
def __init__(self, lie_algebra, **kwargs):
253377
r"""
254378
Initialize ``self``.
255379
@@ -262,7 +386,7 @@ def __init__(self, lie_algebra):
262386
R = lie_algebra.base_ring()
263387
cat = Modules(R).WithBasis().FiniteDimensional()
264388
Representation_abstract.__init__(self, lie_algebra)
265-
CombinatorialFreeModule.__init__(self, R, ['v'], prefix='T', category=cat)
389+
CombinatorialFreeModule.__init__(self, R, ['v'], prefix='T', category=cat, **kwargs)
266390

267391
def _repr_(self):
268392
r"""

src/sage/categories/finite_dimensional_lie_algebras_with_basis.py

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,37 +1532,6 @@ def morphism(self, on_generators, codomain=None, base_map=None, check=True):
15321532
return LieAlgebraMorphism_from_generators(on_generators, domain=self,
15331533
codomain=codomain, base_map=base_map, check=check)
15341534

1535-
def representation(self, f=None):
1536-
"""
1537-
Return a representation of ``self``.
1538-
1539-
Currently the only implementated method of constructing a
1540-
representation is by explicitly specifying the action of
1541-
the basis elements of ``self`` by matrices using a ``dict``.
1542-
1543-
If no arguments are given, then this returns the trivial
1544-
representation.
1545-
1546-
.. SEEALSO::
1547-
1548-
:class:`~sage.algebras.lie_algebras.representation.RepresentationByMorphism`
1549-
1550-
EXAMPLES::
1551-
1552-
sage: L.<x,y> = LieAlgebra(QQ, {('x','y'): {'y':1}})
1553-
sage: f = {x: Matrix([[1,0],[0,0]]), y: Matrix([[0,1],[0,0]])}
1554-
sage: L.representation(f)
1555-
Representation of Lie algebra on 2 generators (x, y) over Rational Field defined by:
1556-
[1 0]
1557-
x |--> [0 0]
1558-
[0 1]
1559-
y |--> [0 0]
1560-
"""
1561-
if f is None:
1562-
return self.trivial_representation()
1563-
from sage.algebras.lie_algebras.representation import RepresentationByMorphism
1564-
return RepresentationByMorphism(self, f)
1565-
15661535
@cached_method
15671536
def universal_polynomials(self):
15681537
r"""

0 commit comments

Comments
 (0)