diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index 90ecf56a5f0..5bde5399c3d 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -17,8 +17,9 @@ #***************************************************************************** from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.structure.element import parent -from sage.categories.lie_algebras import LieAlgebras +from sage.categories.kac_moody_algebras import KacMoodyAlgebras from sage.algebras.lie_algebras.lie_algebra import LieAlgebra, FinitelyGeneratedLieAlgebra from sage.algebras.lie_algebras.lie_algebra_element import UntwistedAffineLieAlgebraElement @@ -27,57 +28,14 @@ from sage.rings.integer_ring import ZZ from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets from sage.sets.family import Family +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.parent import Set_generic class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): r""" An (untwisted) affine Lie algebra. - Let `R` be a ring. Given a finite-dimensional simple Lie algebra - `\mathfrak{g}` over `R`, the affine Lie algebra - `\widehat{\mathfrak{g}}^{\prime}` associated to `\mathfrak{g}` is - defined as - - .. MATH:: - - \widehat{\mathfrak{g}}' = \bigl( \mathfrak{g} \otimes - R[t, t^{-1}] \bigr) \oplus R c, - - where `c` is the canonical central element and `R[t, t^{-1}]` is the - Laurent polynomial ring over `R`. The Lie bracket is defined as - - .. MATH:: - - [x \otimes t^m + \lambda c, y \otimes t^n + \mu c] = - [x, y] \otimes t^{m+n} + m \delta_{m,-n} ( x | y ) c, - - where `( x | y )` is the Killing form on `\mathfrak{g}`. - - There is a canonical derivation `d` on `\widehat{\mathfrak{g}}'` - that is defined by - - .. MATH:: - - d(x \otimes t^m + \lambda c) = a \otimes m t^m, - - or equivalently by `d = t \frac{d}{dt}`. - - The affine Kac-Moody algebra `\widehat{\mathfrak{g}}` is formed by - adjoining the derivation `d` such that - - .. MATH:: - - \widehat{\mathfrak{g}} = \bigl( \mathfrak{g} \otimes R[t,t^{-1}] - \bigr) \oplus R c \oplus R d. - - Specifically, the bracket on `\widehat{\mathfrak{g}}` is defined as - - .. MATH:: - - [t^m \otimes x \oplus \lambda c \oplus \mu d, t^n \otimes y \oplus - \lambda_1 c \oplus \mu_1 d] = \bigl( t^{m+n} [x,y] + \mu n t^n \otimes - y - \mu_1 m t^m \otimes x\bigr) \oplus m \delta_{m,-n} (x|y) c . - Note that the derived subalgebra of the Kac-Moody algebra is the affine Lie algebra. @@ -96,44 +54,10 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): to ``False`` to obtain the affine Lie algebra instead of the affine Kac-Moody algebra. - EXAMPLES: + .. SEEALSO:: - We begin by constructing an affine Kac-Moody algebra of type `G_2^{(1)}` - from the classical Lie algebra of type `G_2`:: - - sage: g = LieAlgebra(QQ, cartan_type=['G',2]) - sage: A = g.affine() - sage: A - Affine Kac-Moody algebra of ['G', 2] in the Chevalley basis - - Next, we construct the generators and perform some computations:: - - sage: A.inject_variables() - Defining e1, e2, f1, f2, h1, h2, e0, f0, c, d - sage: e1.bracket(f1) - (h1)#t^0 - sage: e0.bracket(f0) - (-h1 - 2*h2)#t^0 + 8*c - sage: e0.bracket(f1) - 0 - sage: A[d, f0] - (-E[3*alpha[1] + 2*alpha[2]])#t^-1 - sage: A([[e0, e2], [[[e1, e2], [e0, [e1, e2]]], e1]]) - (-6*E[-3*alpha[1] - alpha[2]])#t^2 - sage: f0.bracket(f1) - 0 - sage: f0.bracket(f2) - (E[3*alpha[1] + alpha[2]])#t^-1 - sage: A[h1+3*h2, A[[[f0, f2], f1], [f1,f2]] + f1] - f1 - (2*E[alpha[1]])#t^-1 - - We can construct its derived subalgebra, the affine Lie algebra - of type `G_2^{(1)}`. In this case, there is no canonical derivation, - so the generator `d` is `0`:: - - sage: D = A.derived_subalgebra() - sage: D.d() - 0 + - :class:`UntwistedAffineLieAlgebra` + - :class:`TwistedAffineLieAlgebra` REFERENCES: @@ -151,13 +75,18 @@ def __classcall_private__(cls, arg0, cartan_type=None, kac_moody=True): EXAMPLES:: - sage: L1 = lie_algebras.Affine(QQ, ['A',4,1]) + sage: L1 = lie_algebras.Affine(QQ, ['A', 4, 1]) sage: cl = lie_algebras.sl(QQ, 5) sage: L2 = lie_algebras.Affine(cl) sage: L1 is L2 True sage: cl.affine() is L1 True + + sage: L1 = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: L2 = lie_algebras.Affine(QQ, ['A', 5, 2]) + sage: L1 is L2 + True """ if isinstance(arg0, LieAlgebra): ct = arg0.cartan_type() @@ -170,25 +99,24 @@ def __classcall_private__(cls, arg0, cartan_type=None, kac_moody=True): cartan_type = CartanType(cartan_type) if not cartan_type.is_affine(): raise ValueError("the Cartan type must be affine") - g = LieAlgebra(arg0, cartan_type=cartan_type.classical()) + if cartan_type.is_untwisted_affine(): + g = LieAlgebra(arg0, cartan_type=cartan_type.classical()) - if not cartan_type.is_untwisted_affine(): - raise NotImplementedError("only currently implemented for untwisted affine types") - return super().__classcall__(cls, g, kac_moody) + if cartan_type.is_untwisted_affine(): + return UntwistedAffineLieAlgebra(g, kac_moody=kac_moody) + return TwistedAffineLieAlgebra(arg0, cartan_type, kac_moody=kac_moody) - def __init__(self, g, kac_moody): + def __init__(self, g, cartan_type, names, kac_moody): """ Initialize ``self``. EXAMPLES:: - sage: asl = lie_algebras.Affine(QQ, ['A',4,1]) + sage: asl = lie_algebras.Affine(QQ, ['D', 4, 1]) sage: TestSuite(asl).run() """ self._g = g - self._cartan_type = g.cartan_type().affine() - R = g.base_ring() - names = list(g.variable_names()) + ['e0', 'f0', 'c'] + self._cartan_type = cartan_type if kac_moody: names += ['d'] @@ -196,30 +124,12 @@ def __init__(self, g, kac_moody): names = tuple(names) self._ordered_indices = names - cat = LieAlgebras(R).WithBasis() + R = g.base_ring() + cat = KacMoodyAlgebras(R).WithBasis() + if not self._cartan_type.is_untwisted_affine(): + cat = cat.Subobjects() FinitelyGeneratedLieAlgebra.__init__(self, R, names, names, category=cat) - def _repr_(self): - r""" - Return a string representation of ``self``. - - EXAMPLES:: - - sage: g = LieAlgebra(QQ, cartan_type=['D',4,1]) - sage: g - Affine Kac-Moody algebra of ['D', 4] in the Chevalley basis - sage: g.derived_subalgebra() - Affine Lie algebra of ['D', 4] in the Chevalley basis - """ - base = "Affine " - rep = repr(self._g) - if self._kac_moody: - old_len = len(rep) - rep = rep.replace("Lie", "Kac-Moody") - if len(rep) == old_len: # We did not replace anything - base += "Kac-Moody " - return base + rep - @cached_method def basis(self): r""" @@ -227,7 +137,7 @@ def basis(self): EXAMPLES:: - sage: g = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: g = LieAlgebra(QQ, cartan_type=['D', 4, 1]) sage: B = g.basis() sage: al = RootSystem(['D',4]).root_lattice().simple_roots() sage: B[al[1]+al[2]+al[4],4] @@ -240,8 +150,21 @@ def basis(self): c sage: B['d'] d + + sage: g = LieAlgebra(QQ, cartan_type=['D', 4, 2], kac_moody=False) + sage: B = g.basis() + sage: it = iter(B) + sage: [next(it) for _ in range(3)] + [c, (E[alpha[1]])#t^0, (E[alpha[2]])#t^0] + sage: B['c'] + c + sage: B['d'] + 0 """ - K = cartesian_product([self._g.basis().keys(), ZZ]) + if self._cartan_type.is_untwisted_affine(): + K = cartesian_product([self._g.basis().keys(), ZZ]) + else: + K = TwistedAffineIndices(self._cartan_type) from sage.sets.finite_enumerated_set import FiniteEnumeratedSet c = FiniteEnumeratedSet(['c']) if self._kac_moody: @@ -294,24 +217,6 @@ def _coerce_map_from_(self, R): return True return super()._coerce_map_from_(R) - def derived_subalgebra(self): - """ - Return the derived subalgebra of ``self``. - - EXAMPLES:: - - sage: g = LieAlgebra(QQ, cartan_type=['B',3,1]) - sage: g - Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis - sage: D = g.derived_subalgebra(); D - Affine Lie algebra of ['B', 3] in the Chevalley basis - sage: D.derived_subalgebra() == D - True - """ - if self._kac_moody: - return AffineLieAlgebra(self._g, kac_moody=False) - return self - def derived_series(self): """ Return the derived series of ``self``. @@ -446,26 +351,117 @@ def lie_algebra_generators(self): (E[alpha[1]])#t^-1, c, d] + + sage: L = LieAlgebra(QQ, cartan_type=['A',5,2]) + sage: list(L.lie_algebra_generators()) + [(E[alpha[1]])#t^0, + (E[alpha[2]])#t^0, + (E[alpha[3]])#t^0, + (E[-alpha[1]])#t^0, + (E[-alpha[2]])#t^0, + (E[-alpha[3]])#t^0, + (h1)#t^0, + (h2)#t^0, + (h3)#t^0, + (E[-alpha[1] - 2*alpha[2] - alpha[3]])#t^1, + (E[alpha[1] + 2*alpha[2] + alpha[3]])#t^-1, + c, + d] """ zero = self.base_ring().zero() d = {} if self._kac_moody: d['d'] = self.d() d['c'] = self.c() + try: finite_gens = dict(self._g.lie_algebra_generators(True)) except TypeError: finite_gens = dict(self._g.lie_algebra_generators()) - for k,g in finite_gens.items(): + for k, g in finite_gens.items(): d[k] = self.element_class(self, {0: g}, zero, zero) - # e_0 = f_{\theta} t - d['e0'] = self.element_class(self, {1: self._g.highest_root_basis_elt(False)}, - zero, zero) - # f_0 = e_{\theta} t^-1 - d['f0'] = self.element_class(self, {-1: self._g.highest_root_basis_elt(True)}, - zero, zero) + + if self._cartan_type.is_untwisted_affine(): + # e_0 = f_{\theta} t + d['e0'] = self.element_class(self, {1: self._g.highest_root_basis_elt(False)}, + zero, zero) + # f_0 = e_{\theta} t^-1 + d['f0'] = self.element_class(self, {-1: self._g.highest_root_basis_elt(True)}, + zero, zero) + elif self._cartan_type.type() != 'BC': + a = self._cartan_type.a() + Q = self._g._Q + theta = Q._from_dict({i: a[i] for i in Q.index_set()}, remove_zeros=False) + # e_0 = f_{\theta} t + d['e0'] = self.element_class(self, {1: self._g.basis()[-theta]}, + zero, zero) + # f_0 = e_{\theta} t^-1 + d['f0'] = self.element_class(self, {-1: self._g.basis()[theta]}, + zero, zero) + else: + n = self._g.cartan_type().rank() + a = self._cartan_type.a() + Q = self._g._Q + theta = Q._from_dict({i: ZZ(2) for i in Q.index_set()}, remove_zeros=False) + # e_0 = f_{\theta} t + d[f'e{n}'] = self.element_class(self, {1: self._g1.basis()[-theta]}, + zero, zero) + # f_0 = e_{\theta} t^-1 + d[f'f{n}'] = self.element_class(self, {-1: self._g1.basis()[theta]}, + zero, zero) + return Family(self.variable_names(), d.__getitem__) + def e(self, i=None): + """ + Return the generators `e` of ``self``. + + INPUT: + + - ``i`` -- (optional) if specified, return just the + generator `e_i` + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B', 3, 1]) + sage: list(g.e()) + [(E[-alpha[1] - 2*alpha[2] - 2*alpha[3]])#t^1, + (E[alpha[1]])#t^0, (E[alpha[2]])#t^0, (E[alpha[3]])#t^0] + sage: g.e(2) + (E[alpha[2]])#t^0 + """ + gens = self.lie_algebra_generators() + if i is None: + I = self._cartan_type.index_set() + d = {j: gens[f'e{j}'] for j in I} + return Family(I, d.__getitem__) + return gens[f'e{i}'] + + def f(self, i=None): + """ + Return the generators `f` of ``self``. + + INPUT: + + - ``i`` -- (optional) if specified, return just the + generator `f_i` + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: list(g.f()) + [(E[alpha[1] + 2*alpha[2] + alpha[3]])#t^-1, + (E[-alpha[1]])#t^0, (E[-alpha[2]])#t^0, (E[-alpha[3]])#t^0] + sage: g.f(2) + (E[-alpha[2]])#t^0 + """ + gens = self.lie_algebra_generators() + if i is None: + I = self._cartan_type.index_set() + d = {j: gens[f'f{j}'] for j in I} + return Family(I, d.__getitem__) + return gens[f'f{i}'] + def monomial(self, m): r""" Construct the monomial indexed by ``m``. @@ -493,4 +489,726 @@ def monomial(self, m): zero = self.base_ring().zero() return self.element_class(self, {m[1]: G[m[0]]}, zero, zero) + +class UntwistedAffineLieAlgebra(AffineLieAlgebra): + r""" + An untwisted affine Lie algebra. + + Let `R` be a ring. Given a finite-dimensional simple Lie algebra + `\mathfrak{g}` over `R`, the affine Lie algebra + `\widehat{\mathfrak{g}}^{\prime}` associated to `\mathfrak{g}` is + defined as + + .. MATH:: + + \widehat{\mathfrak{g}}' = \bigl( \mathfrak{g} \otimes + R[t, t^{-1}] \bigr) \oplus R c, + + where `c` is the canonical central element and `R[t, t^{-1}]` is the + Laurent polynomial ring over `R`. The Lie bracket is defined as + + .. MATH:: + + [x \otimes t^m + \lambda c, y \otimes t^n + \mu c] = + [x, y] \otimes t^{m+n} + m \delta_{m,-n} ( x | y ) c, + + where `( x | y )` is the Killing form on `\mathfrak{g}`. + + There is a canonical derivation `d` on `\widehat{\mathfrak{g}}'` + that is defined by + + .. MATH:: + + d(x \otimes t^m + \lambda c) = a \otimes m t^m, + + or equivalently by `d = t \frac{d}{dt}`. + + The affine Kac-Moody algebra `\widehat{\mathfrak{g}}` is formed by + adjoining the derivation `d` such that + + .. MATH:: + + \widehat{\mathfrak{g}} = \bigl( \mathfrak{g} \otimes R[t,t^{-1}] + \bigr) \oplus R c \oplus R d. + + Specifically, the bracket on `\widehat{\mathfrak{g}}` is defined as + + .. MATH:: + + [t^m \otimes x \oplus \lambda c \oplus \mu d, t^n \otimes y \oplus + \lambda_1 c \oplus \mu_1 d] = \bigl( t^{m+n} [x,y] + \mu n t^n \otimes + y - \mu_1 m t^m \otimes x\bigr) \oplus m \delta_{m,-n} (x|y) c . + + EXAMPLES: + + We begin by constructing an affine Kac-Moody algebra of type `G_2^{(1)}` + from the classical Lie algebra of type `G_2`:: + + sage: g = LieAlgebra(QQ, cartan_type=['G',2]) + sage: A = g.affine() + sage: A + Affine Kac-Moody algebra of ['G', 2] in the Chevalley basis + + Next, we construct the generators and perform some computations:: + + sage: A.inject_variables() + Defining e1, e2, f1, f2, h1, h2, e0, f0, c, d + sage: e1.bracket(f1) + (h1)#t^0 + sage: e0.bracket(f0) + (-h1 - 2*h2)#t^0 + 8*c + sage: e0.bracket(f1) + 0 + sage: A[d, f0] + (-E[3*alpha[1] + 2*alpha[2]])#t^-1 + sage: A([[e0, e2], [[[e1, e2], [e0, [e1, e2]]], e1]]) + (-6*E[-3*alpha[1] - alpha[2]])#t^2 + sage: f0.bracket(f1) + 0 + sage: f0.bracket(f2) + (E[3*alpha[1] + alpha[2]])#t^-1 + sage: A[h1+3*h2, A[[[f0, f2], f1], [f1,f2]] + f1] - f1 + (2*E[alpha[1]])#t^-1 + + We can construct its derived subalgebra, the affine Lie algebra + of type `G_2^{(1)}`. In this case, there is no canonical derivation, + so the generator `d` is `0`:: + + sage: D = A.derived_subalgebra() + sage: D.d() + 0 + """ + def __init__(self, g, kac_moody): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: asl = lie_algebras.Affine(QQ, ['A',4,1]) + sage: TestSuite(asl).run() + """ + cartan_type = g.cartan_type().affine() + names = list(g.variable_names()) + ['e0', 'f0', 'c'] + super().__init__(g, cartan_type, names, kac_moody) + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: g + Affine Kac-Moody algebra of ['D', 4] in the Chevalley basis + sage: g.derived_subalgebra() + Affine Lie algebra of ['D', 4] in the Chevalley basis + """ + base = "Affine " + rep = repr(self._g) + if self._kac_moody: + old_len = len(rep) + rep = rep.replace("Lie", "Kac-Moody") + if len(rep) == old_len: # We did not replace anything + base += "Kac-Moody " + return base + rep + + def derived_subalgebra(self): + """ + Return the derived subalgebra of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: g + Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis + sage: D = g.derived_subalgebra(); D + Affine Lie algebra of ['B', 3] in the Chevalley basis + sage: D.derived_subalgebra() == D + True + """ + if self._kac_moody: + return UntwistedAffineLieAlgebra(self._g, kac_moody=False) + return self + Element = UntwistedAffineLieAlgebraElement + + +class TwistedAffineLieAlgebra(AffineLieAlgebra): + r""" + A twisted affine Lie algebra. + + A twisted affine Lie algebra is an affine Lie algebra for + type `X_N^{(r)}` with `r > 1`. We realize this inside an + untwisted affine Kac--Moody Lie algebra following Chapter 8 + of [Ka1990]_. + + Let `\overline{\mathfrak{g}}` be the classical Lie algebra by + taking the index set `I \setminus \{\epsilon\}`, where + `\epsilon = 0` unless `\epsilon = n` for `X_N^{(r)} = A_{2n}^{(2)}`, + for the twisted affine Lie algebra `\widetilde{\mathfrak{g}}`. + Let `\mathfrak{g}` be the basic Lie algebra of type `X_N`. + We realize `\overline{\mathfrak{g}}` as the fixed-point subalgebra + `\mathfrak{g}^{(0)}` of `\mathfrak{g}` under the order `r` diagram + automorphism `\mu`. This naturally acts on the `\zeta_r` (a primitive + `r`-th root of unity) eigenspace `\mathfrak{g}^{(1)}` of `\mu`, + which is the highest weight representation corresponding to + the small adjoint (where the weight spaces are the short roots + of `\overline{\mathfrak{g}}`). The *twisted affine (Kac-Moody) + Lie algebra* `\widehat{\mathfrak{g}}` is constructed as the + subalgebra of `X_N^{(1)}` given by + + .. MATH:: + + \sum_{i \in \ZZ} \mathfrak{g}^{(i \mod 2)} \otimes t^i + \oplus R c \oplus R d, + + where `R` is the base ring. + + We encode our basis by using the classical Lie algebra except + for type `A_{2n}^{(2)}`. For type `A_{2n}^{(2)}`, the fixed-point + algebra `\mathfrak{g}^{(0)}` is of type `B_n` using the index set + `\{0, \ldots, n-1\}`. For `\mathfrak{g}^{(1)}`, we identify the + weights in this representation with the roots of type `B_n` and + the double all of its short roots. + """ + def __init__(self, R, cartan_type, kac_moody): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: g = lie_algebras.Affine(QQ, ['A', 5, 2]) + sage: TestSuite(g).run() + + sage: g = lie_algebras.Affine(QQ, ['D', 4, 2]) + sage: TestSuite(g).run() + + sage: g = lie_algebras.Affine(QQ, ['D', 5, 2]) + sage: TestSuite(g).run() + + sage: g = lie_algebras.Affine(QQ, ['A', 6, 2]) + sage: TestSuite(g).run() + + sage: g = lie_algebras.Affine(QQ, ['A', 2, 2]) + sage: TestSuite(g).run() + + sage: g = lie_algebras.Affine(QQ, ['E', 6, 2]) + sage: TestSuite(g).run() # long time + + sage: g = lie_algebras.Affine(QQ, ['D', 4, 3]) + sage: TestSuite(g).run() # long time + """ + # basic setup for AffineLieAlgebra + if cartan_type.type() == 'BC': + classical = cartan_type.classical().dual() + n = classical.rank() + classical = classical.relabel({n-i: i for i in range(n)}) + else: + classical = cartan_type.classical() + g = LieAlgebra(R, cartan_type=classical) + n = classical.rank() + names = ['e%s' % i for i in range(1, n+1)] + names.extend('f%s' % i for i in range(1, n+1)) + if cartan_type.type() == 'BC': + names.extend('h%s' % i for i in range(n)) + else: + names.extend('h%s' % i for i in range(1, n+1)) + names += ['e0', 'f0', 'c'] + super().__init__(g, cartan_type, names, kac_moody) + + # setup the ambient simply-laced algebra + basic_ct = cartan_type.basic_untwisted() + if cartan_type.dual().type() == 'B': + ep = [(i, i+1) for i in range(1, n)] + ep.extend((i+1, i) for i in range(n, 2*n-1)) + elif cartan_type.dual().type() == 'F': + ep = [(1, 3), (3, 4), (5, 4), (6, 5), (4, 2)] + elif cartan_type.dual().type() == 'G': + ep = [(1, 2), (3, 2), (4, 2)] + else: + ep = basic_ct.dynkin_diagram().to_undirected().edges(labels=False, sort=False) + + if self._cartan_type.dual().type() == 'G': + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + RP = PolynomialRing(R, 'x') + Rext = RP.quotient(RP.gen(0)**3 - 1) + self._basic = LieAlgebra(Rext, cartan_type=basic_ct, epsilon=ep) + else: + self._basic = LieAlgebra(R, cartan_type=basic_ct, epsilon=ep) + self._ambient = self._basic.affine(kac_moody=self._kac_moody) + + # setup the embeddings + basic_ct = self._basic.cartan_type() + if self._cartan_type.dual().type() == 'G': + gens = basic_ct.dynkin_diagram().automorphism_group().gens() + auto = gens[0] * gens[1] + else: + auto = basic_ct.dynkin_diagram().automorphism_group().gen(0) + basic_Q = basic_ct.root_system().root_lattice() + basic_p_roots = basic_Q.positive_roots() + visited = set() + orbits = [] + for al in basic_p_roots: + if al in visited: + continue + visited.add(al) + O = [al] + cur = basic_Q._from_dict({auto(i): c for i, c in al}, remove_zeros=False) + while cur != al: + O.append(cur) + visited.add(cur) + cur = basic_Q._from_dict({auto(i): c for i, c in cur}, remove_zeros=False) + orbits.append(O) + + finite_ct = self._g.cartan_type() + Q = finite_ct.root_system().root_lattice() + I = finite_ct.index_set() + a = finite_ct.symmetrizer() + ord = auto.order() + + if self._cartan_type.dual().type() == 'F': + # For E_6^(2), we need to take into account the lack of index sets matching + reindex = {2: 4, 4: 3, 3: 2, 1: 1} + + def build_root(O): + return Q._from_dict({reindex[i]: c * (ord // a[reindex[i]]) / len(O) for i, c in sum(O) if i in reindex}, + remove_zeros=False) + elif self._cartan_type.type() == 'BC': + reindex = {n-i: i for i in range(finite_ct.rank())} + + def build_root(O): + return Q._from_dict({reindex[i]: c * (ord // len(O)) for i, c in sum(O) if i in reindex}, + remove_zeros=False) + else: + + def build_root(O): + return Q._from_dict({i: c * (ord // a[i]) / len(O) for i, c in sum(O) if i in I}, + remove_zeros=False) + + self._root_mapping = {build_root(O): O for O in orbits} + for r in list(self._root_mapping.keys()): + self._root_mapping[-r] = [-s for s in self._root_mapping[r]] + if self._cartan_type.type() == 'BC': + assert set(r for r in self._root_mapping if len(self._root_mapping[r]) > 1) == set(Q.roots()) + if self._cartan_type.rank() == 2: + # Special case since sl_2 has only 1 root length + assert set(r / 2 for r in self._root_mapping if len(self._root_mapping[r]) == 1) == set(Q.roots()) + else: + assert set(r / 2 for r in self._root_mapping if len(self._root_mapping[r]) == 1) == set(Q.short_roots()) + from sage.combinat.free_module import CombinatorialFreeModule + X = sorted(self._root_mapping, key=str) + self._g1 = CombinatorialFreeModule(R, X, prefix='E') + else: + assert set(self._root_mapping) == set(Q.roots()) + al = Q.simple_roots() + ac = Q.simple_coroots() + for i in I: + self._root_mapping[ac[i]] = [r.associated_coroot() for r in self._root_mapping[al[i]]] + self._inverse_root_map = {O[0]: r for r, O in self._root_mapping.items()} + + def _repr_(self): + r""" + Return a string representation of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['D', 4, 2]) + sage: g + Twisted affine Kac-Moody algebra of type ['C', 3, 1]^* over Rational Field + sage: g.derived_subalgebra() + Twisted affine Lie algebra of type ['C', 3, 1]^* over Rational Field + """ + rep = "Twisted affine " + rep += "Kac-Moody " if self._kac_moody else "Lie " + rep += f"algebra of type {self._cartan_type} over {self.base_ring()}" + return rep + + def _test_classical_subalgebra(self, **options): + r""" + Test the Chevalley basis properties for the classical subalgebra + of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: L._test_classical_subalgebra() + sage: L = LieAlgebra(QQ, cartan_type=['D', 4, 2]) + sage: L._test_classical_subalgebra() + """ + tester = self._tester(**options) + B = self.basis() + roots = set(self._g._Q.roots()) + ac = list(self._g._Q.simple_coroots()) + from sage.misc.misc import some_tuples + for r, s in some_tuples(roots, 2, tester._max_runs): + ret = B[r,0].bracket(B[s,0]) + if r + s in roots: + tester.assertEqual(list(ret.support()), [(r+s, 0)], f"obtained [{r}, {s}] == {ret}") + elif r == -s: + supp = set((ac, 0) for ac in r.associated_coroot().monomials()) + tester.assertEqual(set(ret.support()), supp, f"obtained [{r}, {s}] == {ret}") + else: + tester.assertEqual(ret, self.zero(), f"nonzero for [{r}, {s}]") + + def derived_subalgebra(self): + r""" + Return the derived subalgebra of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: g + Twisted affine Kac-Moody algebra of type ['B', 3, 1]^* over Rational Field + sage: D = g.derived_subalgebra(); D + Twisted affine Lie algebra of type ['B', 3, 1]^* over Rational Field + sage: D.derived_subalgebra() == D + True + """ + if self._kac_moody: + return TwistedAffineLieAlgebra(self.base_ring(), self._cartan_type, kac_moody=False) + return self + + def ambient(self): + r""" + Return the ambient untwisted affine Lie algebra of ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: g.ambient() + Affine Kac-Moody algebra of ['A', 5] in the Chevalley basis + """ + return self._ambient + + def retract(self, x): + r""" + Retract the element ``x`` from the ambient untwisted affine Lie + algebra into ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: it = iter(g.basis()) + sage: elts = [next(it) for _ in range(20)] + sage: elts + [c, + d, + (E[alpha[1]])#t^0, + (E[alpha[2]])#t^0, + (E[alpha[3]])#t^0, + (E[alpha[1] + alpha[2]])#t^0, + (E[alpha[2] + alpha[3]])#t^0, + (E[2*alpha[2] + alpha[3]])#t^0, + (E[alpha[1] + alpha[2] + alpha[3]])#t^0, + (E[2*alpha[1] + 2*alpha[2] + alpha[3]])#t^0, + (E[alpha[1] + 2*alpha[2] + alpha[3]])#t^0, + (E[-alpha[1]])#t^0, + (E[-alpha[2]])#t^0, + (E[-alpha[3]])#t^0, + (E[-alpha[1] - alpha[2]])#t^0, + (E[-alpha[2] - alpha[3]])#t^0, + (E[-2*alpha[2] - alpha[3]])#t^0, + (E[-alpha[1] - alpha[2] - alpha[3]])#t^0, + (E[-2*alpha[1] - 2*alpha[2] - alpha[3]])#t^0, + (E[-alpha[1] - 2*alpha[2] - alpha[3]])#t^0] + sage: all(g.retract(g.to_ambient(x)) == x for x in elts) + True + """ + t_dict = x.t_dict() + c_coeff = x.c_coefficient() + d_coeff = x.d_coefficient() + if self._cartan_type.dual().type() == 'G': + R = self.base_ring() + for i in t_dict: + t_dict[i] = self._g._from_dict({self._inverse_root_map[r]: R(c.lift()) + for r, c in t_dict[i] if r in self._inverse_root_map}, + remove_zeros=False) + elif self._cartan_type.type() == 'BC': + for i in t_dict: + if i % 2: + t_dict[i] = self._g1._from_dict({self._inverse_root_map[r]: c for r, c in t_dict[i] + if r in self._inverse_root_map}, + remove_zeros=False) + else: + t_dict[i] = self._g._from_dict({self._inverse_root_map[r]: c for r, c in t_dict[i] + if r in self._inverse_root_map}, + remove_zeros=False) + else: + for i in t_dict: + t_dict[i] = self._g._from_dict({self._inverse_root_map[r]: c for r, c in t_dict[i] + if r in self._inverse_root_map}, + remove_zeros=False) + return self.element_class(self, t_dict, c_coeff, d_coeff) + + @lazy_attribute + def to_ambient(self): + r""" + Lift the element ``x`` from the ambient untwisted affine Lie + algebra into ``self``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 5, 2]) + sage: g.to_ambient + Generic morphism: + From: Twisted affine Kac-Moody algebra of type ['B', 3, 1]^* over Rational Field + To: Affine Kac-Moody algebra of ['A', 5] in the Chevalley basis + """ + one = self.base_ring().one() + + if self._cartan_type.type() == 'BC': + mone = -one + + def basis_map(r): + O = self._root_mapping[r] + return self._basic._from_dict({O[0]: one, O[1]: mone**(1+O[1].height())}, + remove_zeros=False) + else: + + def basis_map(r): + return self._basic._from_dict({s: one for s in self._root_mapping[r]}, remove_zeros=False) + + if self._cartan_type.dual().type() == 'G': + zeta3 = self._basic.base_ring().gen() + + def basis_alt(r): + return self._basic._from_dict({s: zeta3**ind for ind, s in enumerate(self._root_mapping[r])}, + remove_zeros=False) + elif self._cartan_type.type() == 'BC': + + def basis_alt(r): + O = self._root_mapping[r] + if len(O) == 1: + return self._basic.monomial(O[0]) + return self._basic._from_dict({O[0]: one, O[1]: mone**O[1].height()}, + remove_zeros=False) + else: + mone = -one + + def basis_alt(r): + return self._basic._from_dict({s: mone**ind for ind, s in enumerate(self._root_mapping[r])}, + remove_zeros=False) + + def lift_map(elt): + t_dict = elt.t_dict() + c_coeff = elt.c_coefficient() + d_coeff = elt.d_coefficient() + for i in t_dict: + if i % 2: + t_dict[i] = self._basic.linear_combination((basis_alt(r), c) + for r, c in t_dict[i]) + else: + t_dict[i] = self._basic.linear_combination((basis_map(r), c) + for r, c in t_dict[i]) + return self._ambient.element_class(self._ambient, t_dict, c_coeff, d_coeff) + + return self.module_morphism(function=lift_map, codomain=self._ambient) + + class Element(UntwistedAffineLieAlgebraElement): + def _bracket_(self, y): + r""" + Return the Lie bracket ``[self, y]``. + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['D', 5, 2]) + sage: e0, e1, e2, e3, e4 = g.e() + sage: f0, f1, f2, f3, f4 = g.f() + sage: B = g.basis() + sage: Q = g.classical().cartan_type().root_system().root_lattice() + sage: h1, h2, h3, h4 = [B[ac, 0] for ac in Q.simple_coroots()] + sage: e1._bracket_(e2) + (-E[alpha[1] + alpha[2]])#t^0 + sage: e1._bracket_(e3) + 0 + sage: e0._bracket_(e1) + (-E[-alpha[2] - alpha[3] - alpha[4]])#t^1 + sage: e0._bracket_(e2) + 0 + sage: f1._bracket_(f2) + (E[-alpha[1] - alpha[2]])#t^0 + sage: f1._bracket_(f3) + 0 + sage: f0._bracket_(f1) + (E[alpha[2] + alpha[3] + alpha[4]])#t^-1 + sage: f0._bracket_(f2) + 0 + sage: g[f0, e0] + (2*h1 + 2*h2 + 2*h3 + h4)#t^0 + -32*c + sage: g([f1, [e1, e2]]) + (E[alpha[2]])#t^0 + sage: g[h1, e0] + (-E[-alpha[1] - alpha[2] - alpha[3] - alpha[4]])#t^1 + sage: g[h2, f0] + 0 + """ + P = parent(self) + ax = P.to_ambient(self) + ay = P.to_ambient(y) + return P.retract(ax.bracket(ay)) + + +class TwistedAffineIndices(UniqueRepresentation, Set_generic): + r""" + The indices for the basis of a twisted affine Lie algebra. + + INPUT: + + - ``cartan_type`` -- the Cartan type of twisted affine type Lie algebra + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.affine_lie_algebra import TwistedAffineIndices + sage: I = TwistedAffineIndices(['A', 3, 2]) + sage: it = iter(I) + sage: [next(it) for _ in range(20)] + [(alpha[1], 0), (alpha[2], 0), (alpha[1] + alpha[2], 0), + (2*alpha[1] + alpha[2], 0), (-alpha[1], 0), (-alpha[2], 0), + (-alpha[1] - alpha[2], 0), (-2*alpha[1] - alpha[2], 0), + (alphacheck[1], 0), (alphacheck[2], 0), (alpha[1], 1), + (alpha[1] + alpha[2], 1), (-alpha[1], 1), (-alpha[1] - alpha[2], 1), + (alphacheck[1], 1), (alpha[1], -1), (alpha[1] + alpha[2], -1), + (-alpha[1], -1), (-alpha[1] - alpha[2], -1), (alphacheck[1], -1)] + + sage: I = TwistedAffineIndices(['A', 4, 2]) + sage: it = iter(I) + sage: [next(it) for _ in range(20)] + [(alpha[0], 0), (alpha[1], 0), (alpha[0] + alpha[1], 0), + (2*alpha[0] + alpha[1], 0), (-alpha[0], 0), (-alpha[1], 0), + (-alpha[0] - alpha[1], 0), (-2*alpha[0] - alpha[1], 0), + (alphacheck[0], 0), (alphacheck[1], 0), (alpha[0], 1), (alpha[1], 1), + (alpha[0] + alpha[1], 1), (2*alpha[0] + alpha[1], 1), (-alpha[0], 1), + (-alpha[1], 1), (-alpha[0] - alpha[1], 1), (-2*alpha[0] - alpha[1], 1), + (2*alpha[0], 1), (2*alpha[0] + 2*alpha[1], 1)] + + sage: I = TwistedAffineIndices(['A', 2, 2]) + sage: it = iter(I) + sage: [next(it) for _ in range(10)] + [(alpha[0], 0), (-alpha[0], 0), (alphacheck[0], 0), (alpha[0], 1), + (-alpha[0], 1), (2*alpha[0], 1), (-2*alpha[0], 1), + (alphacheck[0], 1), (alpha[0], -1), (-alpha[0], -1)] + """ + @staticmethod + def __classcall_private__(cls, cartan_type): + """ + Normalize input to ensure a unique representation. + + sage: from sage.algebras.lie_algebras.affine_lie_algebra import TwistedAffineIndices + sage: I1 = TwistedAffineIndices(CartanType(['C', 4, 1]).dual()) + sage: I2 = TwistedAffineIndices(['D', 5, 2]) + sage: I1 is I2 + True + sage: I = TwistedAffineIndices(['C', 4, 1]) + Traceback (most recent call last): + ... + ValueError: the Cartan type must be a twisted affine type + """ + cartan_type = CartanType(cartan_type) + if not cartan_type.is_affine() or cartan_type.is_untwisted_affine(): + raise ValueError("the Cartan type must be a twisted affine type") + return super().__classcall__(cls, cartan_type) + + def __init__(self, cartan_type): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.affine_lie_algebra import TwistedAffineIndices + sage: I = TwistedAffineIndices(['D', 4, 2]) + sage: TestSuite(I).run() + """ + self._cartan_type = cartan_type + if cartan_type.type() == 'BC': + finite_ct = cartan_type.classical().dual() + n = finite_ct.rank() + Q = finite_ct.relabel({n-i: i for i in range(n)}).root_system().root_lattice() + self._roots = tuple(Q.roots()) + self._ac = tuple(Q.simple_coroots()) + CP = cartesian_product([range(3)] * n) + if cartan_type.rank() == 2: + self._short_roots = self._roots + tuple(2*r for r in Q.roots()) + else: + self._short_roots = self._roots + tuple(2*r for r in Q.short_roots()) + self._short_roots += self._ac + facade = cartesian_product([self._short_roots, ZZ]) + else: + Q = cartan_type.classical().root_system().root_lattice() + self._roots = tuple(Q.roots()) + self._ac = tuple(Q.simple_coroots()) + self._short_roots = tuple(Q.short_roots()) + ac = Q.simple_coroots() + self._short_roots += tuple([ac[i] for i in Q.index_set() if Q.simple_root(i).is_short_root()]) + facade = cartesian_product([self._roots + self._ac, ZZ]) + from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets + super().__init__(facade=facade, category=InfiniteEnumeratedSets()) + + def __contains__(self, x): + """ + Return if ``x`` is contained in ``self``. + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.affine_lie_algebra import TwistedAffineIndices + sage: I = TwistedAffineIndices(['D', 4, 2]) + sage: Q = RootSystem(['B', 3]).root_lattice() + sage: all((r, 4) in I for r in Q.roots()) + True + sage: all((r, 3) in I for r in Q.short_roots()) + True + sage: all((r, 3) not in I for r in Q.long_roots()) + True + sage: list(I.an_element()) in I # lists are not included + False + sage: (5, Q) in I + False + sage: (5, 5) in I + False + sage: (Q.simple_root(1), Q.simple_root(1)) in I + False + sage: (Q.simple_coroot(2), 1) in I + False + sage: (Q.simple_coroot(3), 1) in I + True + """ + if x not in self._facade_for[0]: + return False + x = self._facade_for[0](x) + # self._short_roots also contains the corresponding coroots + return (x[1] % 2 == 0) or x[0] in self._short_roots + + def __iter__(self): + """ + Iterate over ``self``. + + EXAMPLES:: + + sage: from sage.algebras.lie_algebras.affine_lie_algebra import TwistedAffineIndices + sage: I = TwistedAffineIndices(['D', 3, 2]) + sage: it = iter(I) + sage: [next(it) for _ in range(22)] + [(alpha[1], 0), (alpha[2], 0), (alpha[1] + 2*alpha[2], 0), (alpha[1] + alpha[2], 0), + (-alpha[1], 0), (-alpha[2], 0), (-alpha[1] - 2*alpha[2], 0), (-alpha[1] - alpha[2], 0), + (alphacheck[1], 0), (alphacheck[2], 0), (alpha[2], 1), (alpha[1] + alpha[2], 1), + (-alpha[2], 1), (-alpha[1] - alpha[2], 1), (alphacheck[2], 1), (alpha[2], -1), + (alpha[1] + alpha[2], -1), (-alpha[2], -1), (-alpha[1] - alpha[2], -1), + (alphacheck[2], -1), (alpha[1], 2), (alpha[2], 2)] + """ + if self._cartan_type.type() == 'BC': + finite_ct = self._cartan_type.classical().dual() + n = finite_ct.rank() + finite_ct = finite_ct.relabel({n-i: i for i in range(n)}) + else: + finite_ct = self._cartan_type.classical() + Q = finite_ct.root_system().root_lattice() + P = self._facade_for[0] + for i in ZZ: + if i % 2: + # self._short_roots also contains the corresponding coroots + for r in self._short_roots: + yield P((r, i)) + else: + for r in self._roots: + yield P((r, i)) + for r in self._ac: + yield P((r, i)) \ No newline at end of file diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index 0134b5fdd96..26e0153a309 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -147,9 +147,10 @@ def __init__(self, R, ct, e, f, h, sparse=True): 2 """ n = len(e) - names = ['e%s'%i for i in range(1, n+1)] - names += ['f%s'%i for i in range(1, n+1)] - names += ['h%s'%i for i in range(1, n+1)] + I = ct.index_set() + names = ['e%s' % i for i in I] + names += ['f%s' % i for i in I] + names += ['h%s' % i for i in I] category = LieAlgebras(R).FiniteDimensional().WithBasis() from sage.sets.finite_enumerated_set import FiniteEnumeratedSet index_set = FiniteEnumeratedSet(names) @@ -162,10 +163,9 @@ def __init__(self, R, ct, e, f, h, sparse=True): self._sparse = sparse gens = tuple(self.gens()) - i_set = ct.index_set() - self._e = Family(dict( (i, gens[c]) for c,i in enumerate(i_set) )) - self._f = Family(dict( (i, gens[n+c]) for c,i in enumerate(i_set) )) - self._h = Family(dict( (i, gens[2*n+c]) for c,i in enumerate(i_set) )) + self._e = Family({i: gens[c] for c, i in enumerate(I)}) + self._f = Family({i: gens[n+c] for c, i in enumerate(I)}) + self._h = Family({i: gens[2*n+c] for c, i in enumerate(I)}) def e(self, i): r""" @@ -392,7 +392,7 @@ def build_assoc(row): for i in range(cur_mat.rank())] return Family(basis) - def affine(self, kac_moody=False): + def affine(self, kac_moody=True): """ Return the affine (Kac-Moody) Lie algebra of ``self``. @@ -403,9 +403,11 @@ def affine(self, kac_moody=False): Special orthogonal Lie algebra of rank 5 over Rational Field sage: so5.affine() Affine Special orthogonal Kac-Moody algebra of rank 5 over Rational Field + sage: so5.affine(False) + Affine Special orthogonal Lie algebra of rank 5 over Rational Field """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra - return AffineLieAlgebra(self, kac_moody) + return AffineLieAlgebra(self, kac_moody=kac_moody) class gl(MatrixLieAlgebraFromAssociative): @@ -964,8 +966,8 @@ def __init__(self, R): TESTS:: - sage: g = LieAlgebra(QQ, cartan_type=['E', 8], representation='matrix') - sage: g + sage: g = LieAlgebra(QQ, cartan_type=['E', 8], representation='matrix') # long time + sage: g # long time Simple matrix Lie algebra of type ['E', 8] over Rational Field We skip the not implemented methods test as it takes too much time:: @@ -985,7 +987,7 @@ def basis(self): EXAMPLES:: - sage: g = LieAlgebra(QQ, cartan_type=['E', 8], representation='matrix') + sage: g = LieAlgebra(QQ, cartan_type=['E', 8], representation='matrix') # long time sage: len(g.basis()) # long time 248 """ @@ -1561,22 +1563,27 @@ class LieAlgebraChevalleyBasis(LieAlgebraWithStructureCoefficients): .. MATH:: \begin{aligned} - [h_i, h_j] & = 0 - \\ [h_i, e_{\beta}] & = A_{\alpha_i, \beta} e_{\beta} - \\ [e_{\beta}, e_{-\beta}] & = \sum_i A_{\beta, \alpha_i} h_i + [h_i, h_j] & = 0, + \\ [h_i, e_{\beta}] & = A_{\alpha_i, \beta} e_{\beta}, + \\ [e_{\beta}, e_{-\beta}] & = \sum_i A_{\beta, \alpha_i} h_i, \\ [e_{\beta}, e_{\gamma}] & = \begin{cases} - N_{\beta,\gamma} e_{\beta + \gamma} & \beta + \gamma \in \Phi \\ - 0 & \text{otherwise.} \end{cases} + N_{\beta,\gamma} e_{\beta + \gamma} & \beta + \gamma \in \Phi, \\ + 0 & \text{otherwise,} \end{cases} \end{aligned} - where `A_{\alpha, \beta} = \frac{2 (\alpha, \beta)}{(\alpha, \alpha)}` and - `N_{\alpha, \beta}` is the maximum such that + where `A_{\alpha, \beta} = \frac{2 (\alpha, \beta)}{(\alpha, \alpha)}` + and `N_{\alpha, \beta}` is the maximum such that `\alpha - N_{\alpha, \beta} \beta \in \Phi`. For computing the signs of the coefficients, see Section 3 of [CMT2003]_. + + .. SEEALSO:: + + For simply-laced types, an alternative construction using an asymmetry + function is given by :class:`LieAlgebraChevalleyBasis_simply_laced`. """ @staticmethod - def __classcall_private__(cls, R, cartan_type): + def __classcall_private__(cls, R, cartan_type, epsilon=None): """ Normalize ``self`` to ensure a unique representation. @@ -1587,11 +1594,50 @@ def __classcall_private__(cls, R, cartan_type): sage: L3 = LieAlgebra(QQ, cartan_type=CartanMatrix(['A', 2])) sage: L1 is L2 and L2 is L3 True + + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(1,2)]) + sage: type(L) + + sage: L = LieAlgebra(QQ, cartan_type=['A', 1], epsilon=[]) + sage: type(L) + + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(2,3)]) + Traceback (most recent call last): + ... + ValueError: not a valid Dynkin orientation + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(1,2), (2,1)]) + Traceback (most recent call last): + ... + ValueError: not a valid Dynkin orientation + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(1,2), (1,1)]) + Traceback (most recent call last): + ... + ValueError: not a valid Dynkin orientation + sage: L = LieAlgebra(QQ, cartan_type=['A', 1], epsilon=[(1,1)]) + Traceback (most recent call last): + ... + ValueError: not a valid Dynkin orientation """ if isinstance(cartan_type, (CartanMatrix, DynkinDiagram_class)): cartan_type = cartan_type.cartan_type() else: cartan_type = CartanType(cartan_type) + if epsilon is not None: + if not cartan_type.is_simply_laced(): + raise ValueError("the Cartan type must be simply-laced with an asymmetry function") + epsilon = frozenset([tuple(p) for p in epsilon]) + if cartan_type.rank() == 1: + if epsilon: + raise ValueError("not a valid Dynkin orientation") + else: + from sage.graphs.graph import Graph + G = Graph(epsilon, multiedges=True, loops=True, format="list_of_edges") + if (G.has_multiple_edges() or G.has_loops() + or cartan_type.dynkin_diagram().to_undirected() != G.to_simple()): + raise ValueError("not a valid Dynkin orientation") + return LieAlgebraChevalleyBasis_simply_laced(R, cartan_type, epsilon) return super().__classcall__(cls, R, cartan_type) def __init__(self, R, cartan_type): @@ -1605,14 +1651,52 @@ def __init__(self, R, cartan_type): """ self._cartan_type = cartan_type self._Q = cartan_type.root_system().root_lattice() - alpha = self._Q.simple_roots() p_roots = list(self._Q.positive_roots_by_height()) n_roots = [-x for x in p_roots] self._p_roots_index = OrderedDict((al, i) for i, al in enumerate(p_roots)) + + alphacheck = self._Q.simple_coroots() + # We pass p_roots and n_roots so we don't have to reconstruct them + s_coeffs = self._construct_struct_coeffs(R, p_roots) + + # Make sure a < b for all (a, b) in the coefficients and flip if necessary + for k in list(s_coeffs): + a, b = k + if self._basis_key(a) > self._basis_key(b): + s_coeffs[(b, a)] = [(index, -v) for index, v in s_coeffs[k].items()] + del s_coeffs[k] + else: + s_coeffs[k] = s_coeffs[k].items() + + I = self._cartan_type.index_set() + names = ['e{}'.format(i) for i in I] + names += ['f{}'.format(i) for i in I] + names += ['h{}'.format(i) for i in I] + category = TriangularKacMoodyAlgebras(R).FiniteDimensional() + index_set = p_roots + list(alphacheck) + n_roots + self._cartan_indices = range(len(p_roots), len(p_roots) + len(alphacheck)) + names = tuple(names) + from sage.sets.finite_enumerated_set import FiniteEnumeratedSet + index_set = FiniteEnumeratedSet(index_set) + LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeffs, names, index_set, + category, prefix='E', bracket='[', + sorting_key=self._basis_key) + + def _construct_struct_coeffs(self, R, p_roots): + """ + Construct the structure coefficients of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1], epsilon=[]) + sage: sorted(L._construct_struct_coeffs(QQ, list(L._Q.positive_roots())).items(), key=str) + [((alpha[1], -alpha[1]), {alphacheck[1]: 1}), + ((alpha[1], alphacheck[1]), {alpha[1]: -2}), + ((alphacheck[1], -alpha[1]), {-alpha[1]: -2})] + """ alphacheck = self._Q.simple_coroots() roots = frozenset(self._Q.roots()) - num_sroots = len(alpha) one = R.one() # Determine the signs for the structure coefficients from the root system @@ -1678,8 +1762,8 @@ def e_coeff(r, s): # [e_r, e_s] and [e_r, f_s] with r != +/-s # We assume s is positive, as otherwise we negate # both r and s and the resulting coefficient - for j, s in enumerate(p_roots[i+1:]): - j += i+1 # Offset + for j, s in enumerate(p_roots[i+1:], start=i+1): + #j += i + 1 # Offset # Since h(s) >= h(r), we have s - r > 0 when s - r is a root # [f_r, e_s] if s - r in p_roots: @@ -1700,26 +1784,7 @@ def e_coeff(r, s): s_coeffs[(r, s)] = {a: c} s_coeffs[(-r, -s)] = {-a: -c} - # Lastly, make sure a < b for all (a, b) in the coefficients and flip if necessary - for k in list(s_coeffs): - a, b = k[0], k[1] - if self._basis_key(a) > self._basis_key(b): - s_coeffs[(b, a)] = [(index, -v) for index, v in s_coeffs[k].items()] - del s_coeffs[k] - else: - s_coeffs[k] = s_coeffs[k].items() - - names = ['e{}'.format(i) for i in range(1, num_sroots+1)] - names += ['f{}'.format(i) for i in range(1, num_sroots+1)] - names += ['h{}'.format(i) for i in range(1, num_sroots+1)] - category = TriangularKacMoodyAlgebras(R).FiniteDimensional() - index_set = p_roots + list(alphacheck) + n_roots - names = tuple(names) - from sage.sets.finite_enumerated_set import FiniteEnumeratedSet - index_set = FiniteEnumeratedSet(index_set) - LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeffs, names, index_set, - category, prefix='E', bracket='[', - sorting_key=self._basis_key) + return s_coeffs def _repr_(self): """ @@ -1923,8 +1988,8 @@ def _weight_action(self, m, wt): alc = wt.parent().simple_coroots() return R(wt.scalar( alc[aci[m]] )) - def affine(self, kac_moody=False): - """ + def affine(self, kac_moody=True): + r""" Return the affine Lie algebra of ``self``. EXAMPLES:: @@ -1934,14 +1999,20 @@ def affine(self, kac_moody=False): Lie algebra of ['C', 3] in the Chevalley basis sage: sp6.affine() Affine Kac-Moody algebra of ['C', 3] in the Chevalley basis + + sage: L = LieAlgebra(QQ, cartan_type=['A',3], epsilon=[(1,2),(3,2)]) + sage: L.affine(False) + Affine Lie algebra of ['A', 3] in the Chevalley basis + sage: L.affine(True) + Affine Kac-Moody algebra of ['A', 3] in the Chevalley basis """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra - return AffineLieAlgebra(self, kac_moody) + return AffineLieAlgebra(self, kac_moody=kac_moody) # Useful in creating the UEA @cached_method def indices_to_positive_roots_map(self): - """ + r""" Return the map from indices to positive roots. EXAMPLES:: @@ -2032,7 +2103,7 @@ def _part_generators(self, positive=False): @cached_method def gens(self): - """ + r""" Return the generators of ``self`` in the order of `e_i`, `f_i`, and `h_i`. @@ -2078,3 +2149,303 @@ def highest_root_basis_elt(self, pos=True): if pos: return B[theta] return B[-theta] + + @cached_method + def killing_form_matrix(self): + r""" + Return the matrix of the Killing form of ``self``. + + The rows and the columns of this matrix are indexed by the + elements of the basis of ``self`` (in the order provided by + :meth:`basis`). + + EXAMPLES:: + + sage: g = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: g.killing_form_matrix() + [ 0 0 0 0 0 6 0 0] + [ 0 0 0 0 0 0 6 0] + [ 0 0 0 0 0 0 0 6] + [ 0 0 0 12 -6 0 0 0] + [ 0 0 0 -6 12 0 0 0] + [ 6 0 0 0 0 0 0 0] + [ 0 6 0 0 0 0 0 0] + [ 0 0 6 0 0 0 0 0] + """ + B = self.basis() + Q = self._Q + from sage.matrix.constructor import matrix + ret = matrix.zero(self.base_ring(), self._M.rank()) + keys = list(B.keys()) + for i, a in enumerate(keys): + for j, b in enumerate(keys[i:], start=i): + if ((a in Q) != (b in Q)) or (a in Q and a + b): + continue + # either a and b are both coroots or a + b == 0 + temp = self.killing_matrix(B[a], B[b]).trace() + ret[i, j] = temp + ret[j, i] = temp + ret.set_immutable() + return ret + + def killing_form(self, x, y): + r""" + Return the Killing form on ``x`` and ``y``, where ``x`` + and ``y`` are two elements of ``self``. + + The Killing form is defined as + + .. MATH:: + + \langle x \mid y \rangle + = \operatorname{tr}\left( \operatorname{ad}_x + \circ \operatorname{ad}_y \right). + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2]) + sage: L.killing_form(L.an_element(), L.an_element()) + 36 + sage: B = L.basis() + sage: matrix([[L.killing_form(a, b) for a in B] for b in B]) + [ 0 0 0 0 0 6 0 0] + [ 0 0 0 0 0 0 6 0] + [ 0 0 0 0 0 0 0 6] + [ 0 0 0 12 -6 0 0 0] + [ 0 0 0 -6 12 0 0 0] + [ 6 0 0 0 0 0 0 0] + [ 0 6 0 0 0 0 0 0] + [ 0 0 6 0 0 0 0 0] + """ + return x.value * self.killing_form_matrix() * y.value + + +class LieAlgebraChevalleyBasis_simply_laced(LieAlgebraChevalleyBasis): + r""" + A finite dimensional simply-laced Lie algebra in the Chevalley basis + with structure coefficients given by an orientation of the Dynkin + diagram. + + We follow Chapter 7.7 of [Ka1990]_, where the structure coefficients + are given by an :meth:`asymmetry function ` defined by + `\varepsilon(\alpha_i, \alpha_j) = -1` if there is an arrow `i \to j` in + the Dynkin quiver (an orientation of the Dynkin diagram). However we twist + `E_{\alpha}` by `\mathrm{sign}(\alpha)` so that `F_i = E_{-\alpha_i}` + rather than its negative. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(2, 1)]) + sage: L.e(1).bracket(L.e(2)) + E[alpha[1] + alpha[2]] + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(1, 2)]) + sage: L.e(1).bracket(L.e(2)) + -E[alpha[1] + alpha[2]] + """ + def __init__(self, R, cartan_type, epsilon): + """ + Initialize ``self``. + + TESTS:: + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(2,1)]) + sage: TestSuite(L).run(elements=list(L.basis())) + sage: L = LieAlgebra(QQ, cartan_type=['D', 4], epsilon=[(2,1), (3,2), (4,2)]) + sage: TestSuite(L).run(elements=list(L.basis())) # long time + """ + self._epsilon = epsilon + super().__init__(R, cartan_type) + + def _construct_struct_coeffs(self, R, p_roots): + r""" + Construct the structure coefficients of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1], epsilon=[]) + sage: sorted(L._construct_struct_coeffs(QQ, list(L._Q.positive_roots())).items(), key=str) + [((alpha[1], -alpha[1]), {alphacheck[1]: 1}), + ((alpha[1], alphacheck[1]), {alpha[1]: -2}), + ((alphacheck[1], -alpha[1]), {-alpha[1]: -2})] + """ + p_roots_set = set(p_roots) + alphacheck = self._Q.simple_coroots() + + s_coeffs = {} + for i, r in enumerate(p_roots): + # [e_r, h_i] and [h_i, f_r] + for ac in alphacheck: + c = r.scalar(ac) + if c == 0: + continue + s_coeffs[(r, ac)] = {r: -c} + s_coeffs[(ac, -r)] = {-r: -c} + + # [e_r, f_r] + s_coeffs[(r, -r)] = {alphacheck[j]: c + for j, c in r.associated_coroot()} + + # [e_r, e_s] and [e_r, f_s] with r != +/-s + # We assume s is positive, as otherwise we negate + # both r and s and the resulting coefficient + for j, s in enumerate(p_roots[i+1:], start=i+1): + if r + s in p_roots_set: + coeff = R.prod((-1)**(ca*cb) if (ii, jj) in self._epsilon or ii == jj else 1 + for ii, ca in r._monomial_coefficients.items() + for jj, cb in s._monomial_coefficients.items()) + s_coeffs[r, s] = {r+s: coeff} + ht = sum(r.coefficients()) + sum(s.coefficients()) + s_coeffs[-r, -s] = {-r-s: -coeff} + if r - s in p_roots_set or s - r in p_roots_set: + coeff = R.prod((-1)**(ca*cb) if (ii, jj) in self._epsilon or ii == jj else 1 + for ii, ca in r._monomial_coefficients.items() + for jj, cb in s._monomial_coefficients.items()) + if r - s in p_roots_set: + s_coeffs[r, -s] = {r-s: -coeff} + s_coeffs[-r, s] = {s-r: coeff} + else: + s_coeffs[r, -s] = {r-s: coeff} + s_coeffs[-r, s] = {s-r: -coeff} + + return s_coeffs + + def asymmetry_function(self): + r""" + Return the asymmetry function of ``self``. + + An *asymmetry function* is a function `\varepsilon : Q \times Q + \to \{1, -1\}` that satisfies the following properties: + + 1. `\varepsilon(\alpha, \alpha) = (-1)^{(\alpha|\alpha)/2}` + 2. bimultiplicativity `\varepsilon(alpha + \alpha', \beta) = + \varepsilon(\alpha, \beta) \varepsilon(\alpha', \beta)` and + `\varepsilon(alpha, \beta + \beta') = + \varepsilon(\alpha, \beta) \varepsilon(\alpha', \beta)`, + + where `(\alpha | \beta)` is the symmetric bilinear form on `Q` given + by the Cartan matrix. Some consequences of these properties are that + `\varepsilon(\alpha, 0) = \varepsilon(0, \beta) = 1` and + `varepsilon(\alpha, \beta) \varepsilon(\beta, \alpha) = + (-1)^{(\alpha|\beta)}`. + + OUTPUT: + + The asymmetry function as a ``dict`` consisting of pairs of all of + the roots of `Q` and `0`. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',2], epsilon=[(2,1)]) + sage: ep = L.asymmetry_function() + sage: al = L.cartan_type().root_system().root_lattice().simple_roots() + sage: ep[al[1], al[2]] + 1 + sage: ep[al[2],al[1]] + -1 + + sage: L = LieAlgebra(QQ, cartan_type=['A',2], epsilon=[(1,2)]) + sage: ep = L.asymmetry_function() + sage: al = L.cartan_type().root_system().root_lattice().simple_roots() + sage: ep[al[1], al[2]] + -1 + sage: ep[al[2],al[1]] + 1 + """ + roots = set(self._Q.roots()) + al = self._Q.simple_roots() + + ep = {(r, r): (-1)**(r.scalar(r.associated_coroot()) // 2) for r in roots} + next_level = set() + for i in self._Q.index_set(): + # ep[i,0] = ep[i,-j] * ep[i,j] = ep[i,0]^2 + # => ep[i,0] = 1 = ep[i,-j] * ep[i,j] + # => ep[-i,0] = 1 = ep[-i,-j] * ep[-i,j] + ep[al[i], self._Q.zero()] = 1 + ep[-al[i], self._Q.zero()] = 1 + for j in self._Q.index_set(): + if i == j or (i, j) in self._epsilon: + ep[al[i], al[j]] = -1 + else: + ep[al[i], al[j]] = 1 + next_level.add((al[i], al[j])) + ep[al[i], -al[j]] = ep[al[i], al[j]] + next_level.add((al[i], -al[j])) + ep[-al[i], al[j]] = ep[al[i], al[j]] + next_level.add((-al[i], al[j])) + ep[-al[i], -al[j]] = ep[al[i], al[j]] + next_level.add((-al[i], -al[j])) + + while next_level: + cur = next_level + next_level = set() + for r, s in cur: + for a in al: + prev = r + temp = r + a + while temp in roots or temp == 0: + if (temp, s) in ep: + break + next_level.add((temp, s)) + ep[temp, s] = ep[prev, s] * ep[a, s] + prev = temp + temp += a + + prev = r + temp = r - a + while temp in roots or temp == 0: + if (temp, s) in ep: + break + next_level.add((temp, s)) + ep[temp, s] = ep[prev, s] * ep[-a, s] + prev = temp + temp -= a + + prev = s + temp = s + a + while temp in roots or temp == 0: + if (r, temp) in ep: + break + next_level.add((r, temp)) + ep[r, temp] = ep[r, prev] * ep[r, a] + prev = temp + temp += a + + prev = s + temp = s - a + while temp in roots or temp == 0: + if (r, temp) in ep: + break + next_level.add((r, temp)) + ep[r, temp] = ep[r, prev] * ep[r, -a] + prev = temp + temp -= a + + return ep + + def _test_structure_coeffs(self, **options): + r""" + Check the structure coefficients using the :meth:`asymmetry_function`. + + EXAMPLES:: + + sage: L = LieAlgebra(ZZ, cartan_type=['A',4], epsilon=[(1,2), (3,2), (3,4)]) + sage: L._test_structure_coeffs() + """ + tester = self._tester(**options) + + ep = self.asymmetry_function() + + roots = set(self._Q.roots()) + p_roots = set(self._Q.positive_roots()) + B = self.basis() + for r in roots: + for s in roots: + if r + s not in roots: + continue + x = B[r].bracket(B[s]) + tester.assertEqual(list(x.support()), [r+s], f"[{r}, {s}] = {x} is not a root vector") + sign = 1 if (r in p_roots) == (s in p_roots) else -1 + if (r + s) not in p_roots: + sign = -sign + tester.assertEqual(x[r+s], sign * ep[r, s], f"[{r}, {s}] = {x[r+s]} != {sign*ep[r,s]}") diff --git a/src/sage/algebras/lie_algebras/lie_algebra.py b/src/sage/algebras/lie_algebras/lie_algebra.py index 87b1a8cee37..5e1d44813ac 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra.py +++ b/src/sage/algebras/lie_algebras/lie_algebra.py @@ -217,7 +217,7 @@ class LieAlgebra(Parent, UniqueRepresentation): # IndexedGenerators): **4.** We can construct a Lie algebra from a Cartan type by using the ``cartan_type`` option:: - sage: L = LieAlgebra(ZZ, cartan_type=['C',3]) + sage: L = LieAlgebra(ZZ, cartan_type=['C', 3]) sage: L.inject_variables() Defining e1, e2, e3, f1, f2, f3, h1, h2, h3 sage: e1.bracket(e2) @@ -229,13 +229,27 @@ class LieAlgebra(Parent, UniqueRepresentation): # IndexedGenerators): sage: L([e2, [e2, e3]]) 2*E[2*alpha[2] + alpha[3]] - sage: L = LieAlgebra(ZZ, cartan_type=['E',6]) + sage: L = LieAlgebra(ZZ, cartan_type=['E', 6]) sage: L Lie algebra of ['E', 6] in the Chevalley basis + When the Cartan type is finite type and simply-laced, we can also + specify an asymmetry function from [Ka1990]_ using a Dynkin diagram + orientation with the ``epsilon`` option:: + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(1, 2)]) + sage: e1, e2 = L.e() + sage: L[e1, e2] + -E[alpha[1] + alpha[2]] + + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], epsilon=[(2, 1)]) + sage: e1, e2 = L.e() + sage: L[e1, e2] + E[alpha[1] + alpha[2]] + We also have matrix versions of the classical Lie algebras:: - sage: L = LieAlgebra(ZZ, cartan_type=['A',2], representation='matrix') + sage: L = LieAlgebra(ZZ, cartan_type=['A', 2], representation='matrix') sage: L.gens() ( [0 1 0] [0 0 0] [0 0 0] [0 0 0] [ 1 0 0] [ 0 0 0] @@ -246,7 +260,7 @@ class LieAlgebra(Parent, UniqueRepresentation): # IndexedGenerators): There is also the compact real form of matrix Lie algebras implemented (the base ring must currently be a field):: - sage: L = LieAlgebra(QQ, cartan_type=['A',2], representation="compact real") + sage: L = LieAlgebra(QQ, cartan_type=['A', 2], representation="compact real") sage: list(L.basis()) [ [ 0 1 0] [ 0 0 1] [ 0 0 0] [ i 0 0] [0 i 0] [0 0 i] @@ -376,7 +390,7 @@ def __classcall_private__(cls, R=None, arg0=None, arg1=None, names=None, # Parse input as a Cartan type # ----- - ct = kwds.get("cartan_type", None) + ct = kwds.pop("cartan_type", None) if ct is not None: from sage.combinat.root_system.cartan_type import CartanType ct = CartanType(ct) @@ -386,16 +400,16 @@ def __classcall_private__(cls, R=None, arg0=None, arg1=None, names=None, kac_moody=kwds.get("kac_moody", True)) if not ct.is_finite(): raise NotImplementedError("non-finite types are not implemented yet, see trac #14901 for details") - rep = kwds.get("representation", "bracket") + rep = kwds.pop("representation", "bracket") if rep == 'bracket': from sage.algebras.lie_algebras.classical_lie_algebra import LieAlgebraChevalleyBasis - return LieAlgebraChevalleyBasis(R, ct) + return LieAlgebraChevalleyBasis(R, ct, **kwds) if rep == 'matrix': from sage.algebras.lie_algebras.classical_lie_algebra import ClassicalMatrixLieAlgebra - return ClassicalMatrixLieAlgebra(R, ct) + return ClassicalMatrixLieAlgebra(R, ct, **kwds) if rep == 'compact real': from sage.algebras.lie_algebras.classical_lie_algebra import MatrixCompactRealForm - return MatrixCompactRealForm(R, ct) + return MatrixCompactRealForm(R, ct, **kwds) raise ValueError("invalid representation") # Parse the remaining arguments diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index f26b19f1441..98aa1bf653b 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -941,6 +941,15 @@ cdef class UntwistedAffineLieAlgebraElement(Element): with ``style`` - ``tensor_symb`` -- the tensor symbol; must be compatible with ``style`` + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['B', 3, 1]) + sage: elt = L.an_element() + sage: elt._repr_generic(str, str, lambda t: "T^{}".format(t), '.', '(x)') + '(E[alpha[3]] + E[alpha[2]] + E[alpha[1]] + h1 + h2 + h3 + E[-alpha[3]] + + E[-alpha[2]] + E[-alpha[1]])(x)T^0 + (E[-alpha[1] - 2*alpha[2] + - 2*alpha[3]])(x)T^1 + (E[alpha[1] + 2*alpha[2] + 2*alpha[3]])(x)T^-1 + c + d' """ ret = style('') mult = style(mult) diff --git a/src/sage/algebras/lie_algebras/structure_coefficients.py b/src/sage/algebras/lie_algebras/structure_coefficients.py index 8eb6033c4c4..16c2cf51029 100644 --- a/src/sage/algebras/lie_algebras/structure_coefficients.py +++ b/src/sage/algebras/lie_algebras/structure_coefficients.py @@ -358,6 +358,31 @@ def from_vector(self, v, order=None, coerce=True): v = self._M(v) return self.element_class(self, v) + def _from_dict(self, d, coerce=False, remove_zeros=False): + r""" + Construct an element of ``self`` from an ``{index: coefficient}`` + dictionary. + + INPUT: + + - ``d`` -- a dictionary ``{index: coeff}`` where each ``index`` is the + index of a basis element and each ``coeff`` belongs to the + coefficient ring ``self.base_ring()`` + - ``coerce`` -- ignored + - ``remove_zeros`` -- ignored + + EXAMPLES:: + + sage: L. = LieAlgebra(QQ, {('x','y'): {'z':1}}) + sage: L._from_dict({'x': -3, 'z': 2, 'y': 0}) + -3*x + 2*z + """ + zero = self._M.base_ring().zero() + ret = [zero] * self._M.rank() + for k, c in d.items(): + ret[self._index_to_pos[k]] = c + return self.element_class(self, self._M(ret)) + def some_elements(self): """ Return some elements of ``self``.