def __init__(self, ct, c, t, base_ring, prefix): r""" Initialize ``self``. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',2], k.gen(0), k.gen(1)) sage: TestSuite(R).run() # long time """ self._c = c self._t = t self._cartan_type = ct self._weyl = RootSystem(ct).root_lattice().weyl_group(prefix=prefix[1]) self._hd = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[0], bracket=False) self._h = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[2], bracket=False) indices = DisjointUnionEnumeratedSets([self._hd, self._weyl, self._h]) CombinatorialFreeModule.__init__( self, base_ring, indices, category=Algebras(base_ring).WithBasis().Graded(), sorting_key=self._genkey)
def __init__(self, base_ring, n, variable_name, filtration): r""" Initialize ``self``. EXAMPLES:: sage: Y = Yangian(QQ, 4, filtration='loop') sage: TestSuite(Y).run(skip="_test_antipode") # Not implemented sage: Y = Yangian(QQ, 4, filtration='natural') sage: G = Y.algebra_generators() sage: elts = [Y.one(), G[1,2,2], G[1,1,4], G[3,3,1], G[1,2,1]*G[2,1,4]] sage: TestSuite(Y).run(elements=elts) # long time """ self._n = n self._filtration = filtration category = HopfAlgebrasWithBasis(base_ring).Filtered() if filtration == 'natural': category = category.Connected() self._index_set = tuple(range(1, n + 1)) # The keys for the basis are tuples (l, i, j) indices = GeneratorIndexingSet(self._index_set) # We note that the generators are non-commutative, but we always sort # them, so they are, in effect, indexed by the free abelian monoid basis_keys = IndexedFreeAbelianMonoid(indices, bracket=False, prefix=variable_name) CombinatorialFreeModule.__init__(self, base_ring, basis_keys, sorting_key=Yangian._term_key, prefix=variable_name, category=category)
def __init__(self, g, basis_key, prefix, **kwds): """ Initialize ``self``. TESTS:: sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() sage: E,F,H = PBW.algebra_generators() sage: TestSuite(PBW).run(elements=[E, F, H]) sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time """ if basis_key is not None: self._basis_key = basis_key else: self._basis_key_inverse = None R = g.base_ring() self._g = g monomials = IndexedFreeAbelianMonoid(g.basis().keys(), prefix, sorting_key=self._monoid_key, **kwds) CombinatorialFreeModule.__init__( self, R, monomials, prefix='', bracket=False, latex_bracket=False, sorting_key=self._monomial_key, category=Algebras(R).WithBasis().Filtered())
def __init__(self, R, q): r""" Initialize ``self``. TESTS:: sage: A = algebras.AlternatingCentralExtensionQuantumOnsager(QQ) sage: TestSuite(A).run() # long time """ I = DisjointUnionEnumeratedSets( [PositiveIntegers(), ZZ, PositiveIntegers()], keepkey=True, facade=True) monomials = IndexedFreeAbelianMonoid(I, prefix='A', bracket=False) self._q = q CombinatorialFreeModule.__init__( self, R, monomials, prefix='', bracket=False, latex_bracket=False, sorting_key=self._monomial_key, category=Algebras(R).WithBasis().Filtered())
def __init__(self, g, q, c): """ Initialize ``self``. TESTS:: sage: O = lie_algebras.OnsagerAlgebra(QQ) sage: Q = O.quantum_group() sage: TestSuite(Q).run() # long time """ self._g = g self._q = q self._c = c self._q_two = q + ~q R = self._q_two.parent() from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid monomials = IndexedFreeAbelianMonoid(g.basis().keys(), prefix='B', bracket=False, sorting_key=self._monoid_key) CombinatorialFreeModule.__init__( self, R, monomials, prefix='', bracket=False, latex_bracket=False, sorting_key=self._monomial_key, category=Algebras(R).WithBasis().Filtered())
def __init__(self, base_ring, n, level, variable_name, filtration): """ Initialize ``self``. EXAMPLES:: sage: Y = Yangian(QQ, 4, 3) sage: TestSuite(Y).run(skip="_test_antipode") """ self._level = level self._n = n self._filtration = filtration category = HopfAlgebrasWithBasis(base_ring).Filtered() self._index_set = tuple(range(1, n + 1)) # The keys for the basis are tuples (l, i, j) indices = GeneratorIndexingSet(self._index_set, level) # We note that the generators are non-commutative, but we always sort # them, so they are, in effect, indexed by the free abelian monoid basis_keys = IndexedFreeAbelianMonoid(indices, bracket=False, prefix=variable_name) CombinatorialFreeModule.__init__(self, base_ring, basis_keys, prefix=variable_name, category=category)
def __init__(self, base_ring, cartan_type, level, twisted): """ Initialize ``self``. EXAMPLES:: sage: Q = QSystem(QQ, ['A',2]) sage: TestSuite(Q).run() sage: Q = QSystem(QQ, ['E',6,2], twisted=True) sage: TestSuite(Q).run() """ self._cartan_type = cartan_type self._level = level self._twisted = twisted indices = tuple(itertools.product(cartan_type.index_set(), [1])) basis = IndexedFreeAbelianMonoid(indices, prefix='Q', bracket=False) # This is used to do the reductions if self._twisted: self._cm = cartan_type.classical().cartan_matrix() else: self._cm = cartan_type.cartan_matrix() self._Irev = {ind: pos for pos, ind in enumerate(self._cm.index_set())} self._poly = PolynomialRing( ZZ, ['q' + str(i) for i in self._cm.index_set()]) category = Algebras(base_ring).Commutative().WithBasis() CombinatorialFreeModule.__init__(self, base_ring, basis, prefix='Q', category=category)
def __init__(self, gp_indices, n, q, bar, R, category, indices_key=None): """ Initialize ``self``. TESTS:: sage: O = algebras.QuantumMatrixCoordinate(3, 2) sage: TestSuite(O).run() """ self._n = n self._q = q if bar is None: def bar(x): return x.subs(q=~self._q) self._bar = bar if indices_key is None: indices = IndexedFreeAbelianMonoid(gp_indices) else: indices = IndexedFreeAbelianMonoid(gp_indices, sorting_key=indices_key) CombinatorialFreeModule.__init__(self, R, indices, category=category)
def __init__(self, ct, c, t, base_ring, prefix): r""" Initialize ``self``. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',2], k.gen(0), k.gen(1)) sage: TestSuite(R).run() # long time """ self._c = c self._t = t self._cartan_type = ct self._weyl = RootSystem(ct).root_lattice().weyl_group(prefix=prefix[1]) self._hd = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[0], bracket=False) self._h = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[2], bracket=False) indices = DisjointUnionEnumeratedSets([self._hd, self._weyl, self._h]) CombinatorialFreeModule.__init__(self, base_ring, indices, category=Algebras(base_ring).WithBasis().Graded(), sorting_key=self._genkey)
def __init__(self, base_ring): """ EXAMPLES:: sage: A = AlgebrasWithBasis(QQ).Filtered().example() sage: x,y,z = A.algebra_generators() sage: TestSuite(A).run(elements=[x*y+z]) """ I = IndexedFreeAbelianMonoid(['x', 'y', 'z'], prefix='U') gen_cmp = lambda x,y: cmp((-len(x), x.to_word_list()), (-len(y), y.to_word_list())) CombinatorialFreeModule.__init__(self, base_ring, I, bracket=False, prefix='', generator_cmp=gen_cmp, category=FilteredAlgebrasWithBasis(base_ring))
def FreeAbelianMonoid(index_set=None, names=None, **kwds): r""" Return a free abelian monoid on `n` generators or with the generators indexed by a set `I`. We construct free abelian monoids by specifing either: - the number of generators and/or the names of the generators - the indexing set for the generators (this ignores the other two inputs) INPUT: - ``index_set`` -- an indexing set for the generators; if an integer, then this becomes `\{0, 1, \ldots, n-1\}` - ``names`` -- names of generators OUTPUT: A free abelian monoid. EXAMPLES:: sage: F.<a,b,c,d,e> = FreeAbelianMonoid(); F Free abelian monoid on 5 generators (a, b, c, d, e) sage: FreeAbelianMonoid(index_set=ZZ) Free abelian monoid indexed by Integer Ring sage: FreeAbelianMonoid(names='x,y') Free abelian monoid on 2 generators (x, y) """ if isinstance(index_set, str): # Swap args (this works if names is None as well) names, index_set = index_set, names if index_set is None and names is not None: if isinstance(names, str): index_set = names.count(',') + 1 else: index_set = len(names) if index_set not in ZZ: if names is not None: names = normalize_names(len(names), names) from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid return IndexedFreeAbelianMonoid(index_set, names=names, **kwds) if names is None: raise ValueError("names must be specified") return FreeAbelianMonoid_factory(index_set, names)
def __init__(self, base_ring): """ EXAMPLES:: sage: A = AlgebrasWithBasis(QQ).Filtered().example() sage: x,y,z = A.algebra_generators() sage: TestSuite(A).run(elements=[x*y+z]) """ I = IndexedFreeAbelianMonoid(['x', 'y', 'z'], prefix='U') CombinatorialFreeModule.__init__( self, base_ring, I, bracket=False, prefix='', sorting_key=self._sort_key, category=FilteredAlgebrasWithBasis(base_ring))
def __init__(self, R, indices, **kwds): """ Initialize ``self``. EXAMPLES:: sage: L = LieAlgebras(QQ).WithBasis().example() sage: UEA = L.universal_enveloping_algebra() sage: TestSuite(UEA).run() """ if 'category' not in kwds: kwds['category'] = Algebras(R).WithBasis() if 'prefix' not in kwds: kwds['prefix'] = 'P' # This is a workaround until IndexedFree(Abelian)Monoid elements compare properly kwds['sorting_key'] = lambda x: x.to_word_list() kwds['sorting_reverse'] = True M = IndexedFreeAbelianMonoid(indices, bracket='') CombinatorialFreeModule.__init__(self, R, M, **kwds)
def free(index_set=None, names=None, **kwds): r""" Return a free abelian monoid on `n` generators or with the generators indexed by a set `I`. A free monoid is constructed by specifing either: - the number of generators and/or the names of the generators, or - the indexing set for the generators. INPUT: - ``index_set`` -- (optional) an index set for the generators; if an integer, then this represents `\{0, 1, \ldots, n-1\}` - ``names`` -- a string or list/tuple/iterable of strings (default: ``'x'``); the generator names or name prefix EXAMPLES:: sage: Monoids.Commutative.free(index_set=ZZ) Free abelian monoid indexed by Integer Ring sage: Monoids().Commutative().free(ZZ) Free abelian monoid indexed by Integer Ring sage: F.<x,y,z> = Monoids().Commutative().free(); F Free abelian monoid indexed by {'x', 'y', 'z'} """ if names is not None: if isinstance(names, str): from sage.rings.all import ZZ if ',' not in names and index_set in ZZ: names = [names + repr(i) for i in range(index_set)] else: names = names.split(',') names = tuple(names) if index_set is None: index_set = names from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid return IndexedFreeAbelianMonoid(index_set, names=names, **kwds)
def __init__(self, base_ring, cartan_type, level): """ Initialize ``self``. EXAMPLES:: sage: Q = QSystem(QQ, ['A',2]) sage: TestSuite(Q).run() """ self._cartan_type = cartan_type self._level = level indices = tuple(itertools.product(cartan_type.index_set(), [1])) basis = IndexedFreeAbelianMonoid(indices, prefix='Q', bracket=False) # This is used to do the reductions self._poly = PolynomialRing( ZZ, ['q' + str(i) for i in cartan_type.index_set()]) category = Algebras(base_ring).Commutative().WithBasis() CombinatorialFreeModule.__init__(self, base_ring, basis, prefix='Q', category=category)
class RationalCherednikAlgebra(CombinatorialFreeModule): r""" A rational Cherednik algebra. Let `k` be a field. Let `W` be a complex reflection group acting on a vector space `\mathfrak{h}` (over `k`). Let `\mathfrak{h}^*` denote the corresponding dual vector space. Let `\cdot` denote the natural action of `w` on `\mathfrak{h}` and `\mathfrak{h}^*`. Let `\mathcal{S}` denote the set of reflections of `W` and `\alpha_s` and `\alpha_s^{\vee}` are the associated root and coroot of `s`. Let `c = (c_s)_{s \in W}` such that `c_s = c_{tst^{-1}}` for all `t \in W`. The *rational Cherednik algebra* is the `k`-algebra `H_{c,t}(W) = T(\mathfrak{h} \oplus \mathfrak{h}^*) \otimes kW` with parameters `c, t \in k` that is subject to the relations: .. MATH:: \begin{aligned} w \alpha & = (w \cdot \alpha) w, \\ \alpha^{\vee} w & = w (w^{-1} \cdot \alpha^{\vee}), \\ \alpha \alpha^{\vee} & = \alpha^{\vee} \alpha + t \langle \alpha^{\vee}, \alpha \rangle + \sum_{s \in \mathcal{S}} c_s \frac{\langle \alpha^{\vee}, \alpha_s \rangle \langle \alpha^{\vee}_s, \alpha \rangle}{ \langle \alpha^{\vee}, \alpha \rangle} s, \end{aligned} where `w \in W` and `\alpha \in \mathfrak{h}` and `\alpha^{\vee} \in \mathfrak{h}^*`. INPUT: - ``ct`` -- a finite Cartan type - ``c`` -- the parameters `c_s` given as an element or a tuple, where the first entry is the one for the long roots and (for non-simply-laced types) the second is for the short roots - ``t`` -- the parameter `t` - ``base_ring`` -- (optional) the base ring - ``prefix`` -- (default: ``('a', 's', 'ac')``) the prefixes .. TODO:: Implement a version for complex reflection groups. REFERENCES: - [GGOR2003]_ - [EM2001]_ """ @staticmethod def __classcall_private__(cls, ct, c=1, t=None, base_ring=None, prefix=('a', 's', 'ac')): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: R1 = algebras.RationalCherednik(['B',2], 1, 1, QQ) sage: R2 = algebras.RationalCherednik(CartanType(['B',2]), [1,1], 1, QQ, ('a', 's', 'ac')) sage: R1 is R2 True """ ct = CartanType(ct) if not ct.is_finite(): raise ValueError("the Cartan type must be finite") if base_ring is None: if t is None: base_ring = QQ else: base_ring = t.parent() if t is None: t = base_ring.one() else: t = base_ring(t) # Normalize the parameter c if isinstance(c, (tuple, list)): if ct.is_simply_laced(): if len(c) != 1: raise ValueError( "1 parameter c_s must be given for simply-laced types") c = (base_ring(c[0]), ) else: if len(c) != 2: raise ValueError( "2 parameters c_s must be given for non-simply-laced types" ) c = (base_ring(c[0]), base_ring(c[1])) else: c = base_ring(c) if ct.is_simply_laced(): c = (c, ) else: c = (c, c) return super(RationalCherednikAlgebra, cls).__classcall__(cls, ct, c, t, base_ring, tuple(prefix)) def __init__(self, ct, c, t, base_ring, prefix): r""" Initialize ``self``. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',2], k.gen(0), k.gen(1)) sage: TestSuite(R).run() # long time """ self._c = c self._t = t self._cartan_type = ct self._weyl = RootSystem(ct).root_lattice().weyl_group(prefix=prefix[1]) self._hd = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[0], bracket=False) self._h = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[2], bracket=False) indices = DisjointUnionEnumeratedSets([self._hd, self._weyl, self._h]) CombinatorialFreeModule.__init__( self, base_ring, indices, category=Algebras(base_ring).WithBasis().Graded(), sorting_key=self._genkey) def _genkey(self, t): """ Construct a key for comparison for a term indexed by ``t``. The key we create is the tuple in the following order: - overall degree - length of the weyl group element - the weyl group element - the element of `\mathfrak{h}` - the element of `\mathfrak{h}^*` EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element()**2 # indirect doctest 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2 """ return (self.degree_on_basis(t), t[1].length(), t[1], str(t[0]), str(t[2])) @lazy_attribute def _reflections(self): """ A dictionary of reflections to a pair of the associated root and coroot. EXAMPLES:: sage: R = algebras.RationalCherednik(['B',2], [1,2], 1, QQ) sage: [R._reflections[k] for k in sorted(R._reflections, key=str)] [(alpha[1], alphacheck[1], 1), (alpha[1] + alpha[2], 2*alphacheck[1] + alphacheck[2], 2), (alpha[2], alphacheck[2], 2), (alpha[1] + 2*alpha[2], alphacheck[1] + alphacheck[2], 1)] """ d = {} for r in RootSystem(self._cartan_type).root_lattice().positive_roots(): s = self._weyl.from_reduced_word(r.associated_reflection()) if r.is_short_root(): c = self._c[1] else: c = self._c[0] d[s] = (r, r.associated_coroot(), c) return d def _repr_(self): r""" Return a string representation of ``self``. EXAMPLES :: sage: RationalCherednikAlgebra(['A',4], 2, 1, QQ) Rational Cherednik Algebra of type ['A', 4] with c=2 and t=1 over Rational Field sage: algebras.RationalCherednik(['B',2], [1,2], 1, QQ) Rational Cherednik Algebra of type ['B', 2] with c_L=1 and c_S=2 and t=1 over Rational Field """ ret = "Rational Cherednik Algebra of type {} with ".format( self._cartan_type) if self._cartan_type.is_simply_laced(): ret += "c={}".format(self._c[0]) else: ret += "c_L={} and c_S={}".format(*self._c) return ret + " and t={} over {}".format(self._t, self.base_ring()) def _repr_term(self, t): """ Return a string representation of the term indexed by ``t``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element() # indirect doctest 3*ac1 + 2*s1 + a1 sage: R.one() # indirect doctest I """ r = [] if t[0] != self._hd.one(): r.append(t[0]) if t[1] != self._weyl.one(): r.append(t[1]) if t[2] != self._h.one(): r.append(t[2]) if not r: return 'I' return '*'.join(repr(x) for x in r) def algebra_generators(self): """ Return the algebra generators of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: list(R.algebra_generators()) [a1, a2, s1, s2, ac1, ac2] """ keys = ['a' + str(i) for i in self._cartan_type.index_set()] keys += ['s' + str(i) for i in self._cartan_type.index_set()] keys += ['ac' + str(i) for i in self._cartan_type.index_set()] def gen_map(k): if k[0] == 's': i = int(k[1:]) return self.monomial( (self._hd.one(), self._weyl.group_generators()[i], self._h.one())) if k[1] == 'c': i = int(k[2:]) return self.monomial((self._hd.one(), self._weyl.one(), self._h.monoid_generators()[i])) i = int(k[1:]) return self.monomial((self._hd.monoid_generators()[i], self._weyl.one(), self._h.one())) return Family(keys, gen_map) @cached_method def one_basis(self): """ Return the index of the element `1`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.one_basis() (1, 1, 1) """ return (self._hd.one(), self._weyl.one(), self._h.one()) def product_on_basis(self, left, right): r""" Return ``left`` multiplied by ``right`` in ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: a2 = R.algebra_generators()['a2'] sage: ac1 = R.algebra_generators()['ac1'] sage: a2 * ac1 # indirect doctest a2*ac1 sage: ac1 * a2 -I + a2*ac1 - s1 - s2 + 1/2*s1*s2*s1 sage: x = R.an_element() sage: [y * x for y in R.some_elements()] [0, 3*ac1 + 2*s1 + a1, 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2, 3*a1*ac1 + 2*a1*s1 + a1^2, 3*a2*ac1 + 2*a2*s1 + a1*a2, 3*s1*ac1 + 2*I - a1*s1, 3*s2*ac1 + 2*s2*s1 + a1*s2 + a2*s2, 3*ac1^2 - 2*s1*ac1 + 2*I + a1*ac1 + 2*s1 + 1/2*s2 + 1/2*s1*s2*s1, 3*ac1*ac2 + 2*s1*ac1 + 2*s1*ac2 - I + a1*ac2 - s1 - s2 + 1/2*s1*s2*s1] sage: [x * y for y in R.some_elements()] [0, 3*ac1 + 2*s1 + a1, 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2, 6*I + 3*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 - 2*a1*s1 + a1^2, -3*I + 3*a2*ac1 - 3*s1 - 3*s2 + 3/2*s1*s2*s1 + 2*a1*s1 + 2*a2*s1 + a1*a2, -3*s1*ac1 + 2*I + a1*s1, 3*s2*ac1 + 3*s2*ac2 + 2*s1*s2 + a1*s2, 3*ac1^2 + 2*s1*ac1 + a1*ac1, 3*ac1*ac2 + 2*s1*ac2 + a1*ac2] """ # Make copies of the internal dictionaries dl = dict(left[2]._monomial) dr = dict(right[0]._monomial) # If there is nothing to commute if not dl and not dr: return self.monomial((left[0], left[1] * right[1], right[2])) R = self.base_ring() I = self._cartan_type.index_set() P = PolynomialRing(R, 'x', len(I)) G = P.gens() gens_dict = {a: G[i] for i, a in enumerate(I)} Q = RootSystem(self._cartan_type).root_lattice() alpha = Q.simple_roots() alphacheck = Q.simple_coroots() def commute_w_hd(w, al): # al is given as a dictionary ret = P.one() for k in al: x = sum(c * gens_dict[i] for i, c in alpha[k].weyl_action(w)) ret *= x**al[k] ret = ret.dict() for k in ret: yield (self._hd({I[i]: e for i, e in enumerate(k) if e != 0}), ret[k]) # Do Lac Ra if they are both non-trivial if dl and dr: il = dl.keys()[0] ir = dr.keys()[0] # Compute the commutator terms = self._product_coroot_root(il, ir) # remove the generator from the elements dl[il] -= 1 if dl[il] == 0: del dl[il] dr[ir] -= 1 if dr[ir] == 0: del dr[ir] # We now commute right roots past the left reflections: s Ra = Ra' s cur = self._from_dict({(hd, s * right[1], right[2]): c * cc for s, c in terms for hd, cc in commute_w_hd(s, dr)}) cur = self.monomial((left[0], left[1], self._h(dl))) * cur # Add back in the commuted h and hd elements rem = self.monomial((left[0], left[1], self._h(dl))) rem = rem * self.monomial( (self._hd({ir: 1}), self._weyl.one(), self._h({il: 1}))) rem = rem * self.monomial((self._hd(dr), right[1], right[2])) return cur + rem if dl: # We have La Ls Lac Rs Rac, # so we must commute Lac Rs = Rs Lac' # and obtain La (Ls Rs) (Lac' Rac) ret = P.one() for k in dl: x = sum(c * gens_dict[i] for i, c in alphacheck[k].weyl_action( right[1].reduced_word(), inverse=True)) ret *= x**dl[k] ret = ret.dict() w = left[1] * right[1] return self._from_dict({ (left[0], w, self._h({I[i]: e for i, e in enumerate(k) if e != 0}) * right[2]): ret[k] for k in ret }) # Otherwise dr is non-trivial and we have La Ls Ra Rs Rac, # so we must commute Ls Ra = Ra' Ls w = left[1] * right[1] return self._from_dict({(left[0] * hd, w, right[2]): c for hd, c in commute_w_hd(left[1], dr)}) @cached_method def _product_coroot_root(self, i, j): r""" Return the product `\alpha^{\vee}_i \alpha_j`. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',3], k.gen(0), k.gen(1)) sage: R._product_coroot_root(1, 1) ((1, 2*t), (s1*s2*s3*s2*s1, 1/2*c), (s2*s3*s2, 1/2*c), (s1*s2*s1, 1/2*c), (s1, 2*c), (s3, 0), (s2, 1/2*c)) sage: R._product_coroot_root(1, 2) ((1, -t), (s1*s2*s3*s2*s1, 0), (s2*s3*s2, -1/2*c), (s1*s2*s1, 1/2*c), (s1, -c), (s3, 0), (s2, -c)) sage: R._product_coroot_root(1, 3) ((1, 0), (s1*s2*s3*s2*s1, 1/2*c), (s2*s3*s2, -1/2*c), (s1*s2*s1, -1/2*c), (s1, 0), (s3, 0), (s2, 1/2*c)) """ Q = RootSystem(self._cartan_type).root_lattice() ac = Q.simple_coroot(i) al = Q.simple_root(j) R = self.base_ring() terms = [(self._weyl.one(), self._t * R(ac.scalar(al)))] for s in self._reflections: # p[0] is the root, p[1] is the coroot, p[2] the value c_s pr, pc, c = self._reflections[s] terms.append( (s, c * R(ac.scalar(pr) * pc.scalar(al) / pc.scalar(pr)))) return tuple(terms) def degree_on_basis(self, m): """ Return the degree on the monomial indexed by ``m``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: [R.degree_on_basis(g.leading_support()) ....: for g in R.algebra_generators()] [1, 1, 0, 0, -1, -1] """ return m[0].length() - m[2].length() @cached_method def trivial_idempotent(self): """ Return the trivial idempotent of ``self``. Let `e = |W|^{-1} \sum_{w \in W} w` is the trivial idempotent. Thus `e^2 = e` and `eW = We`. The trivial idempotent is used in the construction of the spherical Cherednik algebra from the rational Cherednik algebra by `U_{c,t}(W) = e H_{c,t}(W) e`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.trivial_idempotent() 1/6*I + 1/6*s1 + 1/6*s2 + 1/6*s2*s1 + 1/6*s1*s2 + 1/6*s1*s2*s1 """ coeff = self.base_ring()(~self._weyl.cardinality()) hd_one = self._hd.one() # root - a h_one = self._h.one() # coroot - ac return self._from_dict({(hd_one, w, h_one): coeff for w in self._weyl}, remove_zeros=False) @cached_method def deformed_euler(self): """ Return the element `eu_k`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.deformed_euler() 2*I + 2/3*a1*ac1 + 1/3*a1*ac2 + 1/3*a2*ac1 + 2/3*a2*ac2 + s1 + s2 + s1*s2*s1 """ I = self._cartan_type.index_set() G = self.algebra_generators() cm = ~CartanMatrix(self._cartan_type) n = len(I) ac = [G['ac' + str(i)] for i in I] la = [ sum(cm[i, j] * G['a' + str(I[i])] for i in range(n)) for j in range(n) ] return self.sum(ac[i] * la[i] for i in range(n)) @cached_method def an_element(self): """ Return an element of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element() 3*ac1 + 2*s1 + a1 """ G = self.algebra_generators() i = str(self._cartan_type.index_set()[0]) return G['a' + i] + 2 * G['s' + i] + 3 * G['ac' + i] def some_elements(self): """ Return some elements of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.some_elements() [0, I, 3*ac1 + 2*s1 + a1, a1, a2, s1, s2, ac1, ac2] """ ret = [self.zero(), self.one(), self.an_element()] ret += list(self.algebra_generators()) return ret
class RationalCherednikAlgebra(CombinatorialFreeModule): r""" A rational Cherednik algebra. Let `k` be a field. Let `W` be a complex reflection group acting on a vector space `\mathfrak{h}` (over `k`). Let `\mathfrak{h}^*` denote the corresponding dual vector space. Let `\cdot` denote the natural action of `w` on `\mathfrak{h}` and `\mathfrak{h}^*`. Let `\mathcal{S}` denote the set of reflections of `W` and `\alpha_s` and `\alpha_s^{\vee}` are the associated root and coroot of `s`. Let `c = (c_s)_{s \in W}` such that `c_s = c_{tst^{-1}}` for all `t \in W`. The *rational Cherednik algebra* is the `k`-algebra `H_{c,t}(W) = T(\mathfrak{h} \oplus \mathfrak{h}^*) \otimes kW` with parameters `c, t \in k` that is subject to the relations: .. MATH:: \begin{aligned} w \alpha & = (w \cdot \alpha) w, \\ \alpha^{\vee} w & = w (w^{-1} \cdot \alpha^{\vee}), \\ \alpha \alpha^{\vee} & = \alpha^{\vee} \alpha + t \langle \alpha^{\vee}, \alpha \rangle + \sum_{s \in \mathcal{S}} c_s \frac{\langle \alpha^{\vee}, \alpha_s \rangle \langle \alpha^{\vee}_s, \alpha \rangle}{ \langle \alpha^{\vee}, \alpha \rangle} s, \end{aligned} where `w \in W` and `\alpha \in \mathfrak{h}` and `\alpha^{\vee} \in \mathfrak{h}^*`. INPUT: - ``ct`` -- a finite Cartan type - ``c`` -- the parameters `c_s` given as an element or a tuple, where the first entry is the one for the long roots and (for non-simply-laced types) the second is for the short roots - ``t`` -- the parameter `t` - ``base_ring`` -- (optional) the base ring - ``prefix`` -- (default: ``('a', 's', 'ac')``) the prefixes .. TODO:: Implement a version for complex reflection groups. REFERENCES: - [GGOR2003]_ - [EM2001]_ """ @staticmethod def __classcall_private__(cls, ct, c=1, t=None, base_ring=None, prefix=('a', 's', 'ac')): """ Normalize input to ensure a unique representation. EXAMPLES:: sage: R1 = algebras.RationalCherednik(['B',2], 1, 1, QQ) sage: R2 = algebras.RationalCherednik(CartanType(['B',2]), [1,1], 1, QQ, ('a', 's', 'ac')) sage: R1 is R2 True """ ct = CartanType(ct) if not ct.is_finite(): raise ValueError("the Cartan type must be finite") if base_ring is None: if t is None: base_ring = QQ else: base_ring = t.parent() if t is None: t = base_ring.one() else: t = base_ring(t) # Normalize the parameter c if isinstance(c, (tuple, list)): if ct.is_simply_laced(): if len(c) != 1: raise ValueError("1 parameter c_s must be given for simply-laced types") c = (base_ring(c[0]),) else: if len(c) != 2: raise ValueError("2 parameters c_s must be given for non-simply-laced types") c = (base_ring(c[0]), base_ring(c[1])) else: c = base_ring(c) if ct.is_simply_laced(): c = (c,) else: c = (c, c) return super(RationalCherednikAlgebra, cls).__classcall__(cls, ct, c, t, base_ring, tuple(prefix)) def __init__(self, ct, c, t, base_ring, prefix): r""" Initialize ``self``. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',2], k.gen(0), k.gen(1)) sage: TestSuite(R).run() # long time """ self._c = c self._t = t self._cartan_type = ct self._weyl = RootSystem(ct).root_lattice().weyl_group(prefix=prefix[1]) self._hd = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[0], bracket=False) self._h = IndexedFreeAbelianMonoid(ct.index_set(), prefix=prefix[2], bracket=False) indices = DisjointUnionEnumeratedSets([self._hd, self._weyl, self._h]) CombinatorialFreeModule.__init__(self, base_ring, indices, category=Algebras(base_ring).WithBasis().Graded(), sorting_key=self._genkey) def _genkey(self, t): """ Construct a key for comparison for a term indexed by ``t``. The key we create is the tuple in the following order: - overall degree - length of the Weyl group element - the Weyl group element - the element of `\mathfrak{h}` - the element of `\mathfrak{h}^*` EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element()**2 # indirect doctest 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2 """ return (self.degree_on_basis(t), t[1].length(), t[1], str(t[0]), str(t[2])) @lazy_attribute def _reflections(self): """ A dictionary of reflections to a pair of the associated root and coroot. EXAMPLES:: sage: R = algebras.RationalCherednik(['B',2], [1,2], 1, QQ) sage: [R._reflections[k] for k in sorted(R._reflections, key=str)] [(alpha[1], alphacheck[1], 1), (alpha[1] + alpha[2], 2*alphacheck[1] + alphacheck[2], 2), (alpha[2], alphacheck[2], 2), (alpha[1] + 2*alpha[2], alphacheck[1] + alphacheck[2], 1)] """ d = {} for r in RootSystem(self._cartan_type).root_lattice().positive_roots(): s = self._weyl.from_reduced_word(r.associated_reflection()) if r.is_short_root(): c = self._c[1] else: c = self._c[0] d[s] = (r, r.associated_coroot(), c) return d def _repr_(self): r""" Return a string representation of ``self``. EXAMPLES :: sage: RationalCherednikAlgebra(['A',4], 2, 1, QQ) Rational Cherednik Algebra of type ['A', 4] with c=2 and t=1 over Rational Field sage: algebras.RationalCherednik(['B',2], [1,2], 1, QQ) Rational Cherednik Algebra of type ['B', 2] with c_L=1 and c_S=2 and t=1 over Rational Field """ ret = "Rational Cherednik Algebra of type {} with ".format(self._cartan_type) if self._cartan_type.is_simply_laced(): ret += "c={}".format(self._c[0]) else: ret += "c_L={} and c_S={}".format(*self._c) return ret + " and t={} over {}".format(self._t, self.base_ring()) def _repr_term(self, t): """ Return a string representation of the term indexed by ``t``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element() # indirect doctest 3*ac1 + 2*s1 + a1 sage: R.one() # indirect doctest I """ r = [] if t[0] != self._hd.one(): r.append(t[0]) if t[1] != self._weyl.one(): r.append(t[1]) if t[2] != self._h.one(): r.append(t[2]) if not r: return 'I' return '*'.join(repr(x) for x in r) def algebra_generators(self): """ Return the algebra generators of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: list(R.algebra_generators()) [a1, a2, s1, s2, ac1, ac2] """ keys = ['a'+str(i) for i in self._cartan_type.index_set()] keys += ['s'+str(i) for i in self._cartan_type.index_set()] keys += ['ac'+str(i) for i in self._cartan_type.index_set()] def gen_map(k): if k[0] == 's': i = int(k[1:]) return self.monomial( (self._hd.one(), self._weyl.group_generators()[i], self._h.one()) ) if k[1] == 'c': i = int(k[2:]) return self.monomial( (self._hd.one(), self._weyl.one(), self._h.monoid_generators()[i]) ) i = int(k[1:]) return self.monomial( (self._hd.monoid_generators()[i], self._weyl.one(), self._h.one()) ) return Family(keys, gen_map) @cached_method def one_basis(self): """ Return the index of the element `1`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.one_basis() (1, 1, 1) """ return (self._hd.one(), self._weyl.one(), self._h.one()) def product_on_basis(self, left, right): r""" Return ``left`` multiplied by ``right`` in ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: a2 = R.algebra_generators()['a2'] sage: ac1 = R.algebra_generators()['ac1'] sage: a2 * ac1 # indirect doctest a2*ac1 sage: ac1 * a2 -I + a2*ac1 - s1 - s2 + 1/2*s1*s2*s1 sage: x = R.an_element() sage: [y * x for y in R.some_elements()] [0, 3*ac1 + 2*s1 + a1, 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2, 3*a1*ac1 + 2*a1*s1 + a1^2, 3*a2*ac1 + 2*a2*s1 + a1*a2, 3*s1*ac1 + 2*I - a1*s1, 3*s2*ac1 + 2*s2*s1 + a1*s2 + a2*s2, 3*ac1^2 - 2*s1*ac1 + 2*I + a1*ac1 + 2*s1 + 1/2*s2 + 1/2*s1*s2*s1, 3*ac1*ac2 + 2*s1*ac1 + 2*s1*ac2 - I + a1*ac2 - s1 - s2 + 1/2*s1*s2*s1] sage: [x * y for y in R.some_elements()] [0, 3*ac1 + 2*s1 + a1, 9*ac1^2 + 10*I + 6*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 + a1^2, 6*I + 3*a1*ac1 + 6*s1 + 3/2*s2 + 3/2*s1*s2*s1 - 2*a1*s1 + a1^2, -3*I + 3*a2*ac1 - 3*s1 - 3*s2 + 3/2*s1*s2*s1 + 2*a1*s1 + 2*a2*s1 + a1*a2, -3*s1*ac1 + 2*I + a1*s1, 3*s2*ac1 + 3*s2*ac2 + 2*s1*s2 + a1*s2, 3*ac1^2 + 2*s1*ac1 + a1*ac1, 3*ac1*ac2 + 2*s1*ac2 + a1*ac2] """ # Make copies of the internal dictionaries dl = dict(left[2]._monomial) dr = dict(right[0]._monomial) # If there is nothing to commute if not dl and not dr: return self.monomial((left[0], left[1] * right[1], right[2])) R = self.base_ring() I = self._cartan_type.index_set() P = PolynomialRing(R, 'x', len(I)) G = P.gens() gens_dict = {a:G[i] for i,a in enumerate(I)} Q = RootSystem(self._cartan_type).root_lattice() alpha = Q.simple_roots() alphacheck = Q.simple_coroots() def commute_w_hd(w, al): # al is given as a dictionary ret = P.one() for k in al: x = sum(c * gens_dict[i] for i,c in alpha[k].weyl_action(w)) ret *= x**al[k] ret = ret.dict() for k in ret: yield (self._hd({I[i]: e for i,e in enumerate(k) if e != 0}), ret[k]) # Do Lac Ra if they are both non-trivial if dl and dr: il = dl.keys()[0] ir = dr.keys()[0] # Compute the commutator terms = self._product_coroot_root(il, ir) # remove the generator from the elements dl[il] -= 1 if dl[il] == 0: del dl[il] dr[ir] -= 1 if dr[ir] == 0: del dr[ir] # We now commute right roots past the left reflections: s Ra = Ra' s cur = self._from_dict({ (hd, s*right[1], right[2]): c * cc for s,c in terms for hd, cc in commute_w_hd(s, dr) }) cur = self.monomial( (left[0], left[1], self._h(dl)) ) * cur # Add back in the commuted h and hd elements rem = self.monomial( (left[0], left[1], self._h(dl)) ) rem = rem * self.monomial( (self._hd({ir:1}), self._weyl.one(), self._h({il:1})) ) rem = rem * self.monomial( (self._hd(dr), right[1], right[2]) ) return cur + rem if dl: # We have La Ls Lac Rs Rac, # so we must commute Lac Rs = Rs Lac' # and obtain La (Ls Rs) (Lac' Rac) ret = P.one() for k in dl: x = sum(c * gens_dict[i] for i,c in alphacheck[k].weyl_action(right[1].reduced_word(), inverse=True)) ret *= x**dl[k] ret = ret.dict() w = left[1]*right[1] return self._from_dict({ (left[0], w, self._h({I[i]: e for i,e in enumerate(k) if e != 0}) * right[2] ): ret[k] for k in ret }) # Otherwise dr is non-trivial and we have La Ls Ra Rs Rac, # so we must commute Ls Ra = Ra' Ls w = left[1]*right[1] return self._from_dict({ (left[0] * hd, w, right[2]): c for hd, c in commute_w_hd(left[1], dr) }) @cached_method def _product_coroot_root(self, i, j): r""" Return the product `\alpha^{\vee}_i \alpha_j`. EXAMPLES:: sage: k = QQ['c,t'] sage: R = algebras.RationalCherednik(['A',3], k.gen(0), k.gen(1)) sage: R._product_coroot_root(1, 1) ((1, 2*t), (s1*s2*s3*s2*s1, 1/2*c), (s2*s3*s2, 1/2*c), (s1*s2*s1, 1/2*c), (s1, 2*c), (s3, 0), (s2, 1/2*c)) sage: R._product_coroot_root(1, 2) ((1, -t), (s1*s2*s3*s2*s1, 0), (s2*s3*s2, -1/2*c), (s1*s2*s1, 1/2*c), (s1, -c), (s3, 0), (s2, -c)) sage: R._product_coroot_root(1, 3) ((1, 0), (s1*s2*s3*s2*s1, 1/2*c), (s2*s3*s2, -1/2*c), (s1*s2*s1, -1/2*c), (s1, 0), (s3, 0), (s2, 1/2*c)) """ Q = RootSystem(self._cartan_type).root_lattice() ac = Q.simple_coroot(i) al = Q.simple_root(j) R = self.base_ring() terms = [( self._weyl.one(), self._t * R(ac.scalar(al)) )] for s in self._reflections: # p[0] is the root, p[1] is the coroot, p[2] the value c_s pr, pc, c = self._reflections[s] terms.append(( s, c * R(ac.scalar(pr) * pc.scalar(al) / pc.scalar(pr)) )) return tuple(terms) def degree_on_basis(self, m): """ Return the degree on the monomial indexed by ``m``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: [R.degree_on_basis(g.leading_support()) ....: for g in R.algebra_generators()] [1, 1, 0, 0, -1, -1] """ return m[0].length() - m[2].length() @cached_method def trivial_idempotent(self): """ Return the trivial idempotent of ``self``. Let `e = |W|^{-1} \sum_{w \in W} w` is the trivial idempotent. Thus `e^2 = e` and `eW = We`. The trivial idempotent is used in the construction of the spherical Cherednik algebra from the rational Cherednik algebra by `U_{c,t}(W) = e H_{c,t}(W) e`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.trivial_idempotent() 1/6*I + 1/6*s1 + 1/6*s2 + 1/6*s2*s1 + 1/6*s1*s2 + 1/6*s1*s2*s1 """ coeff = self.base_ring()(~self._weyl.cardinality()) hd_one = self._hd.one() # root - a h_one = self._h.one() # coroot - ac return self._from_dict({(hd_one, w, h_one): coeff for w in self._weyl}, remove_zeros=False) @cached_method def deformed_euler(self): """ Return the element `eu_k`. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.deformed_euler() 2*I + 2/3*a1*ac1 + 1/3*a1*ac2 + 1/3*a2*ac1 + 2/3*a2*ac2 + s1 + s2 + s1*s2*s1 """ I = self._cartan_type.index_set() G = self.algebra_generators() cm = ~CartanMatrix(self._cartan_type) n = len(I) ac = [G['ac'+str(i)] for i in I] la = [sum(cm[i,j]*G['a'+str(I[i])] for i in range(n)) for j in range(n)] return self.sum(ac[i]*la[i] for i in range(n)) @cached_method def an_element(self): """ Return an element of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.an_element() 3*ac1 + 2*s1 + a1 """ G = self.algebra_generators() i = str(self._cartan_type.index_set()[0]) return G['a'+i] + 2*G['s'+i] + 3*G['ac'+i] def some_elements(self): """ Return some elements of ``self``. EXAMPLES:: sage: R = algebras.RationalCherednik(['A',2], 1, 1, QQ) sage: R.some_elements() [0, I, 3*ac1 + 2*s1 + a1, a1, a2, s1, s2, ac1, ac2] """ ret = [self.zero(), self.one(), self.an_element()] ret += list(self.algebra_generators()) return ret