def character(self, R=None): """ Returns the character of this crystal. INPUT: - ``R`` -- a :class:`WeylCharacterRing` (default: the default :class:`WeylCharacterRing` for this Cartan type) Returns the character of ``self`` as an element of ``R``. EXAMPLES:: sage: C = crystals.Tableaux("A2", shape=[2,1]) sage: chi = C.character(); chi A2(2,1,0) sage: T = crystals.TensorProduct(C,C) sage: chiT = T.character(); chiT A2(2,2,2) + 2*A2(3,2,1) + A2(3,3,0) + A2(4,1,1) + A2(4,2,0) sage: chiT == chi^2 True One may specify an alternate :class:`WeylCharacterRing`:: sage: R = WeylCharacterRing("A2", style="coroots") sage: chiT = T.character(R); chiT A2(0,0) + 2*A2(1,1) + A2(0,3) + A2(3,0) + A2(2,2) sage: chiT in R True It should have the same Cartan type and use the same realization of the weight lattice as ``self``:: sage: R = WeylCharacterRing("A3", style="coroots") sage: T.character(R) Traceback (most recent call last): ... ValueError: Weyl character ring does not have the right Cartan type """ from sage.combinat.root_system.weyl_characters import WeylCharacterRing if R is None: R = WeylCharacterRing(self.cartan_type()) if not R.cartan_type() == self.cartan_type(): raise ValueError( "Weyl character ring does not have the right Cartan type") assert R.basis().keys() == self.weight_lattice_realization() return R.sum_of_monomials(x.weight() for x in self.highest_weight_vectors())
def character(self, R=None): """ Returns the character of this crystal. INPUT: - ``R`` -- a :class:`WeylCharacterRing` (default: the default :class:`WeylCharacterRing` for this Cartan type) Returns the character of ``self`` as an element of ``R``. EXAMPLES:: sage: C = CrystalOfTableaux("A2", shape=[2,1]) sage: chi = C.character(); chi A2(2,1,0) sage: T = TensorProductOfCrystals(C,C) sage: chiT = T.character(); chiT A2(2,2,2) + 2*A2(3,2,1) + A2(3,3,0) + A2(4,1,1) + A2(4,2,0) sage: chiT == chi^2 True One may specify an alternate :class:`WeylCharacterRing`:: sage: R = WeylCharacterRing("A2", style="coroots") sage: chiT = T.character(R); chiT A2(0,0) + 2*A2(1,1) + A2(0,3) + A2(3,0) + A2(2,2) sage: chiT in R True It should have the same cartan type and use the same realization of the weight lattice as ``self``:: sage: R = WeylCharacterRing("A3", style="coroots") sage: T.character(R) Traceback (most recent call last): ... ValueError: Weyl character ring does not have the right Cartan type """ from sage.combinat.root_system.weyl_characters import WeylCharacterRing if R == None: R = WeylCharacterRing(self.cartan_type()) if not R.cartan_type() == self.cartan_type(): raise ValueError, "Weyl character ring does not have the right Cartan type" assert R.basis().keys() == self.weight_lattice_realization() return R.sum_of_monomials( x.weight() for x in self.highest_weight_vectors() )
def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5): r""" Return the branching rule on ``self``. Removing any node from the extended Dynkin diagram of the affine Lie algebra results in the Dynkin diagram of a classical Lie algebra, which is therefore a Lie subalgebra. For example removing the `0` node from the Dynkin diagram of type ``[X, r, 1]`` produces the classical Dynkin diagram of ``[X, r]``. Thus for each `i` in the index set, we may restrict ``self`` to the corresponding classical subalgebra. Of course ``self`` is an infinite dimensional representation, but each weight `\mu` is assigned a grading by the number of times the simple root `\alpha_i` appears in `\Lambda-\mu`. Thus the branched representation is graded and we get sequence of finite-dimensional representations which this method is able to compute. OPTIONAL: - ``i`` -- (default: 0) an element of the index set - ``weyl_character_ring`` -- a WeylCharacterRing - ``sequence`` -- a dictionary - ``depth`` -- (default: 5) an upper bound for `k` determining how many terms to give In the default case where `i = 0`, you do not need to specify anything else, though you may want to increase the depth if you need more terms. EXAMPLES:: sage: Lambda = RootSystem(['A',2,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(2*Lambda[0]) sage: b = V.branch(); b [A2(0,0), A2(1,1), A2(0,0) + 2*A2(1,1) + A2(2,2), 2*A2(0,0) + 2*A2(0,3) + 4*A2(1,1) + 2*A2(3,0) + 2*A2(2,2), 4*A2(0,0) + 3*A2(0,3) + 10*A2(1,1) + 3*A2(3,0) + A2(1,4) + 6*A2(2,2) + A2(4,1), 6*A2(0,0) + 9*A2(0,3) + 20*A2(1,1) + 9*A2(3,0) + 3*A2(1,4) + 12*A2(2,2) + 3*A2(4,1) + A2(3,3)] If the parameter ``weyl_character_ring`` is omitted, the ring may be recovered as the parent of one of the branched coefficients:: sage: A2 = b[0].parent(); A2 The Weyl Character Ring of Type A2 with Integer Ring coefficients If `i` is not zero then you should specify the :class:`WeylCharacterRing` that you are branching to. This is determined by the Dynkin diagram:: sage: Lambda = RootSystem(['B',3,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(Lambda[0]) sage: V.cartan_type().dynkin_diagram() O 0 | | O---O=>=O 1 2 3 B3~ In this example, we observe that removing the `i=2` node from the Dynkin diagram produces a reducible diagram of type ``A1xA1xA1``. Thus we have a branching to `\mathfrak{sl}(2) \times \mathfrak{sl}(2) \times \mathfrak{sl}(2)`:: sage: A1xA1xA1 = WeylCharacterRing("A1xA1xA1",style="coroots") sage: V.branch(i=2,weyl_character_ring=A1xA1xA1) [A1xA1xA1(1,0,0), A1xA1xA1(0,1,2), A1xA1xA1(1,0,0) + A1xA1xA1(1,2,0) + A1xA1xA1(1,0,2), A1xA1xA1(2,1,2) + A1xA1xA1(0,1,0) + 2*A1xA1xA1(0,1,2), 3*A1xA1xA1(1,0,0) + 2*A1xA1xA1(1,2,0) + A1xA1xA1(1,2,2) + 2*A1xA1xA1(1,0,2) + A1xA1xA1(1,0,4) + A1xA1xA1(3,0,0), A1xA1xA1(2,1,0) + 3*A1xA1xA1(2,1,2) + 2*A1xA1xA1(0,1,0) + 5*A1xA1xA1(0,1,2) + A1xA1xA1(0,1,4) + A1xA1xA1(0,3,2)] If the nodes of the two Dynkin diagrams are not in the same order, you must specify an additional parameter, ``sequence`` which gives a dictionary to the affine Dynkin diagram to the classical one. EXAMPLES:: sage: Lambda = RootSystem(['F',4,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(Lambda[0]) sage: V.cartan_type().dynkin_diagram() O---O---O=>=O---O 0 1 2 3 4 F4~ sage: A1xC3=WeylCharacterRing("A1xC3",style="coroots") sage: A1xC3.dynkin_diagram() O 1 O---O=<=O 2 3 4 A1xC3 Observe that removing the `i=1` node from the ``F4~`` Dynkin diagram gives the ``A1xC3`` diagram, but the roots are in a different order. The nodes `0, 2, 3, 4` of ``F4~`` correspond to ``1, 4, 3, 2`` of ``A1xC3`` and so we encode this in a dictionary:: sage: V.branch(i=1,weyl_character_ring=A1xC3,sequence={0:1,2:4,3:3,4:2}) # long time [A1xC3(1,0,0,0), A1xC3(0,0,0,1), A1xC3(1,0,0,0) + A1xC3(1,2,0,0), A1xC3(2,0,0,1) + A1xC3(0,0,0,1) + A1xC3(0,1,1,0), 2*A1xC3(1,0,0,0) + A1xC3(1,0,1,0) + 2*A1xC3(1,2,0,0) + A1xC3(1,0,2,0) + A1xC3(3,0,0,0), 2*A1xC3(2,0,0,1) + A1xC3(2,1,1,0) + A1xC3(0,1,0,0) + 3*A1xC3(0,0,0,1) + 2*A1xC3(0,1,1,0) + A1xC3(0,2,0,1)] The branch method gives a way of computing the graded dimension of the integrable representation:: sage: Lambda = RootSystem("A1~").weight_lattice(extended=true).fundamental_weights() sage: V=IntegrableRepresentation(Lambda[0]) sage: r = [x.degree() for x in V.branch(depth=15)]; r [1, 3, 4, 7, 13, 19, 29, 43, 62, 90, 126, 174, 239, 325, 435, 580] sage: oeis(r) # optional -- internet 0: A029552: Expansion of phi(x) / f(-x) in powers of x where phi(), f() are Ramanujan theta functions. """ if i is None: i = self._cartan_type.special_node() if i == self._cartan_type.special_node() or self._cartan_type.type( ) == 'A': if weyl_character_ring is None: weyl_character_ring = WeylCharacterRing( self._cartan_type.classical(), style="coroots") if weyl_character_ring.cartan_type( ) != self._cartan_type.classical(): raise ValueError( "Cartan type of WeylCharacterRing must be %s" % self.cartan_type().classical()) elif weyl_character_ring is None: raise ValueError( "the argument weyl_character_ring cannot be omitted if i != 0") if sequence is None: sequence = {} for j in self._index_set: if j < i: sequence[j] = j + 1 elif j > i: sequence[j] = j def next_level(x): ret = [] for j in self._index_set: t = list(x[0]) t[j] += 1 t = tuple(t) m = self.m(t) if m > 0 and t[i] <= depth: ret.append((t, m)) return ret hwv = (tuple([0 for j in self._index_set]), 1) terms = RecursivelyEnumeratedSet([hwv], next_level) fw = weyl_character_ring.fundamental_weights() P = self.weight_lattice() ret = [] for l in range(depth + 1): lterms = [x for x in terms if x[0][i] == l] ldict = {} for x in lterms: mc = P(self.to_weight(x[0])).monomial_coefficients() contr = sum(fw[sequence[j]] * mc.get(j, 0) for j in self._index_set if j != i).coerce_to_sl() if contr in ldict: ldict[contr] += x[1] else: ldict[contr] = x[1] ret.append(weyl_character_ring.char_from_weights(ldict)) return ret
def branch(self, i=None, weyl_character_ring=None, sequence=None, depth=5): r""" Return the branching rule on ``self``. Removing any node from the extended Dynkin diagram of the affine Lie algebra results in the Dynkin diagram of a classical Lie algebra, which is therefore a Lie subalgebra. For example removing the `0` node from the Dynkin diagram of type ``[X, r, 1]`` produces the classical Dynkin diagram of ``[X, r]``. Thus for each `i` in the index set, we may restrict ``self`` to the corresponding classical subalgebra. Of course ``self`` is an infinite dimensional representation, but each weight `\mu` is assigned a grading by the number of times the simple root `\alpha_i` appears in `\Lambda-\mu`. Thus the branched representation is graded and we get sequence of finite-dimensional representations which this method is able to compute. OPTIONAL: - ``i`` -- (default: 0) an element of the index set - ``weyl_character_ring`` -- a WeylCharacterRing - ``sequence`` -- a dictionary - ``depth`` -- (default: 5) an upper bound for `k` determining how many terms to give In the default case where `i = 0`, you do not need to specify anything else, though you may want to increase the depth if you need more terms. EXAMPLES:: sage: Lambda = RootSystem(['A',2,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(2*Lambda[0]) sage: b = V.branch(); b [A2(0,0), A2(1,1), A2(0,0) + 2*A2(1,1) + A2(2,2), 2*A2(0,0) + 2*A2(0,3) + 4*A2(1,1) + 2*A2(3,0) + 2*A2(2,2), 4*A2(0,0) + 3*A2(0,3) + 10*A2(1,1) + 3*A2(3,0) + A2(1,4) + 6*A2(2,2) + A2(4,1), 6*A2(0,0) + 9*A2(0,3) + 20*A2(1,1) + 9*A2(3,0) + 3*A2(1,4) + 12*A2(2,2) + 3*A2(4,1) + A2(3,3)] If the parameter ``weyl_character_ring`` is omitted, the ring may be recovered as the parent of one of the branched coefficients:: sage: A2 = b[0].parent(); A2 The Weyl Character Ring of Type A2 with Integer Ring coefficients If `i` is not zero then you should specify the :class:`WeylCharacterRing` that you are branching to. This is determined by the Dynkin diagram:: sage: Lambda = RootSystem(['B',3,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(Lambda[0]) sage: V.cartan_type().dynkin_diagram() O 0 | | O---O=>=O 1 2 3 B3~ In this example, we observe that removing the `i=2` node from the Dynkin diagram produces a reducible diagram of type ``A1xA1xA1``. Thus we have a branching to `\mathfrak{sl}(2) \times \mathfrak{sl}(2) \times \mathfrak{sl}(2)`:: sage: A1xA1xA1 = WeylCharacterRing("A1xA1xA1",style="coroots") sage: V.branch(i=2,weyl_character_ring=A1xA1xA1) [A1xA1xA1(1,0,0), A1xA1xA1(0,1,2), A1xA1xA1(1,0,0) + A1xA1xA1(1,2,0) + A1xA1xA1(1,0,2), A1xA1xA1(2,1,2) + A1xA1xA1(0,1,0) + 2*A1xA1xA1(0,1,2), 3*A1xA1xA1(1,0,0) + 2*A1xA1xA1(1,2,0) + A1xA1xA1(1,2,2) + 2*A1xA1xA1(1,0,2) + A1xA1xA1(1,0,4) + A1xA1xA1(3,0,0), A1xA1xA1(2,1,0) + 3*A1xA1xA1(2,1,2) + 2*A1xA1xA1(0,1,0) + 5*A1xA1xA1(0,1,2) + A1xA1xA1(0,1,4) + A1xA1xA1(0,3,2)] If the nodes of the two Dynkin diagrams are not in the same order, you must specify an additional parameter, ``sequence`` which gives a dictionary to the affine Dynkin diagram to the classical one. EXAMPLES:: sage: Lambda = RootSystem(['F',4,1]).weight_lattice(extended=true).fundamental_weights() sage: V = IntegrableRepresentation(Lambda[0]) sage: V.cartan_type().dynkin_diagram() O---O---O=>=O---O 0 1 2 3 4 F4~ sage: A1xC3=WeylCharacterRing("A1xC3",style="coroots") sage: A1xC3.dynkin_diagram() O 1 O---O=<=O 2 3 4 A1xC3 Observe that removing the `i=1` node from the ``F4~`` Dynkin diagram gives the ``A1xC3`` diagram, but the roots are in a different order. The nodes `0, 2, 3, 4` of ``F4~`` correspond to ``1, 4, 3, 2`` of ``A1xC3`` and so we encode this in a dictionary:: sage: V.branch(i=1,weyl_character_ring=A1xC3,sequence={0:1,2:4,3:3,4:2}) # long time [A1xC3(1,0,0,0), A1xC3(0,0,0,1), A1xC3(1,0,0,0) + A1xC3(1,2,0,0), A1xC3(2,0,0,1) + A1xC3(0,0,0,1) + A1xC3(0,1,1,0), 2*A1xC3(1,0,0,0) + A1xC3(1,0,1,0) + 2*A1xC3(1,2,0,0) + A1xC3(1,0,2,0) + A1xC3(3,0,0,0), 2*A1xC3(2,0,0,1) + A1xC3(2,1,1,0) + A1xC3(0,1,0,0) + 3*A1xC3(0,0,0,1) + 2*A1xC3(0,1,1,0) + A1xC3(0,2,0,1)] The branch method gives a way of computing the graded dimension of the integrable representation:: sage: Lambda = RootSystem("A1~").weight_lattice(extended=true).fundamental_weights() sage: V=IntegrableRepresentation(Lambda[0]) sage: r = [x.degree() for x in V.branch(depth=15)]; r [1, 3, 4, 7, 13, 19, 29, 43, 62, 90, 126, 174, 239, 325, 435, 580] sage: oeis(r) # optional -- internet 0: A029552: Expansion of phi(x) / f(-x) in powers of x where phi(), f() are Ramanujan theta functions. """ if i is None: i = self._cartan_type.special_node() if i == self._cartan_type.special_node() or self._cartan_type.type() == 'A': if weyl_character_ring is None: weyl_character_ring = WeylCharacterRing(self._cartan_type.classical(), style="coroots") if weyl_character_ring.cartan_type() != self._cartan_type.classical(): raise ValueError("Cartan type of WeylCharacterRing must be %s"%self.cartan_type().classical()) elif weyl_character_ring is None: raise ValueError("the argument weyl_character_ring cannot be omitted if i != 0") if sequence is None: sequence = {} for j in self._index_set: if j < i: sequence[j] = j+1 elif j > i: sequence[j] = j def next_level(x): ret = [] for j in self._index_set: t = list(x[0]) t[j] += 1 t = tuple(t) m = self.m(t) if m > 0 and t[i] <= depth: ret.append((t,m)) return ret hwv = (tuple([0 for j in self._index_set]), 1) terms = RecursivelyEnumeratedSet([hwv], next_level) fw = weyl_character_ring.fundamental_weights() P = self.weight_lattice() ret = [] for l in range(depth+1): lterms = [x for x in terms if x[0][i] == l] ldict = {} for x in lterms: mc = P(self.to_weight(x[0])).monomial_coefficients() contr = sum(fw[sequence[j]]*mc.get(j,0) for j in self._index_set if j != i).coerce_to_sl() if contr in ldict: ldict[contr] += x[1] else: ldict[contr] = x[1] ret.append(weyl_character_ring.char_from_weights(ldict)) return ret