Example #1
0
    def maximal_elements(self):
        r"""
        Return the maximal elements of ``self`` with respect to Bruhat order.

        The current implementation is via a conjectural type-free
        formula. Use maximal_elements_combinatorial() for proven
        type-specific implementations. To compare type-free and
        type-specific (combinatorial) implementations, use method
        :meth:`_test_maximal_elements`.

        EXAMPLES::

            sage: W = WeylGroup(['A',4,1])
            sage: PF = W.pieri_factors()
            sage: sorted([w.reduced_word() for w in PF.maximal_elements()], key=str)
            [[0, 4, 3, 2], [1, 0, 4, 3], [2, 1, 0, 4], [3, 2, 1, 0], [4, 3, 2, 1]]

            sage: W = WeylGroup(RootSystem(["C",3,1]).weight_space())
            sage: PF = W.pieri_factors()
            sage: sorted([w.reduced_word() for w in PF.maximal_elements()], key=str)
            [[0, 1, 2, 3, 2, 1], [1, 0, 1, 2, 3, 2], [1, 2, 3, 2, 1, 0],
             [2, 1, 0, 1, 2, 3], [2, 3, 2, 1, 0, 1], [3, 2, 1, 0, 1, 2]]

            sage: W = WeylGroup(RootSystem(["B",3,1]).weight_space())
            sage: PF = W.pieri_factors()
            sage: sorted([w.reduced_word() for w in PF.maximal_elements()], key=str)
            [[0, 2, 3, 2, 0], [1, 0, 2, 3, 2], [1, 2, 3, 2, 1],
             [2, 1, 0, 2, 3], [2, 3, 2, 1, 0], [3, 2, 1, 0, 2]]

            sage: W = WeylGroup(['D',4,1])
            sage: PF = W.pieri_factors()
            sage: sorted([w.reduced_word() for w in PF.maximal_elements()], key=str)
            [[0, 2, 4, 3, 2, 0], [1, 0, 2, 4, 3, 2], [1, 2, 4, 3, 2, 1],
             [2, 1, 0, 2, 4, 3], [2, 4, 3, 2, 1, 0], [3, 2, 1, 0, 2, 3],
             [4, 2, 1, 0, 2, 4], [4, 3, 2, 1, 0, 2]]
        """
        ct = self.W.cartan_type()
        s = ct.translation_factors()[1]
        R = RootSystem(ct).weight_space()
        Lambda = R.fundamental_weights()
        orbit = [
            R.reduced_word_of_translation(x) for x in (
                s * (Lambda[1] - Lambda[1].level() * Lambda[0]))._orbit_iter()
        ]
        return [self.W.from_reduced_word(x) for x in orbit]
Example #2
0
    def __init__(self, cartan_type, starting_weight):
        """
        EXAMPLES::

            sage: C = CrystalOfLSPaths(['A',2,1],[-1,0,1]); C
            The crystal of LS paths of type ['A', 2, 1] and weight (-1, 0, 1)
            sage: C.R
            Root system of type ['A', 2, 1]
            sage: C.weight
            -Lambda[0] + Lambda[2]
            sage: C.weight.parent()
            Extended weight space over the Rational Field of the Root system of type ['A', 2, 1]
            sage: C.module_generators
            [(-Lambda[0] + Lambda[2],)]
        """
        self._cartan_type = CartanType(cartan_type)
        self.R = RootSystem(cartan_type)

        self._name = "The crystal of LS paths of type %s and weight %s"%(cartan_type,starting_weight)

        if self._cartan_type.is_affine():
            self.extended = True
            if all(i>=0 for i in starting_weight):
                Parent.__init__(self, category = HighestWeightCrystals())
            else:
                Parent.__init__(self, category = Crystals())
        else:
            self.extended = False
            Parent.__init__(self, category = FiniteCrystals())

        Lambda = self.R.weight_space(extended = self.extended).basis()
        offset = self.R.index_set()[Integer(0)]

        zero_weight = self.R.weight_space(extended = self.extended).zero()
        self.weight = sum([zero_weight]+[starting_weight[j-offset]*Lambda[j] for j in self.R.index_set()])

        if self.weight == zero_weight:
            initial_element = self(tuple([]))
        else:
            initial_element = self(tuple([self.weight]))
        self.module_generators = [initial_element]
Example #3
0
    def weight_in_root_lattice(self):
        r"""
        Return the weight of ``self`` as an element of the root lattice.

        EXAMPLES::

            sage: M = crystals.infinity.NakajimaMonomials(['F',4])
            sage: m = M.module_generators[0].f_string([3,3,1,2,4])
            sage: m.weight_in_root_lattice()
            -alpha[1] - alpha[2] - 2*alpha[3] - alpha[4]

            sage: M = crystals.infinity.NakajimaMonomials(['B',3,1])
            sage: mg = M.module_generators[0]
            sage: m = mg.f_string([1,3,2,0,1,2,3,0,0,1])
            sage: m.weight_in_root_lattice()
            -3*alpha[0] - 3*alpha[1] - 2*alpha[2] - 2*alpha[3]
        """
        Q = RootSystem(self.parent().cartan_type()).root_lattice()
        alpha = Q.simple_roots()
        path = self.to_highest_weight()
        return Q(sum(-alpha[j] for j in path[1]))
Example #4
0
    def __classcall_private__(cls, starting_weight, cartan_type=None):
        """
        Classcall to mend the input.

        Internally, the
        :class:`~sage.combinat.crystals.littlemann_path.CrystalOfLSPaths` code
        works with a ``starting_weight`` that is in the weight space associated
        to the crystal. The user can, however, also input a ``cartan_type``
        and the coefficients of the fundamental weights as
        ``starting_weight``. This code transforms the input into the right
        format (also necessary for UniqueRepresentation).

        TESTS::

            sage: crystals.LSPaths(['A',2,1],[-1,0,1])
            The crystal of LS paths of type ['A', 2, 1] and weight -Lambda[0] + Lambda[2]

            sage: R = RootSystem(['B',2,1])
            sage: La = R.weight_space().basis()
            sage: C = crystals.LSPaths(['B',2,1],[0,0,1])
            sage: B = crystals.LSPaths(La[2])
            sage: B is C
            True
        """
        if cartan_type is not None:
            cartan_type, starting_weight = CartanType(
                starting_weight), cartan_type
            if cartan_type.is_affine():
                extended = True
            else:
                extended = False

            R = RootSystem(cartan_type)
            P = R.weight_space(extended=extended)
            Lambda = P.basis()
            offset = R.index_set()[Integer(0)]
            starting_weight = P.sum(starting_weight[j - offset] * Lambda[j]
                                    for j in R.index_set())

        return super(CrystalOfLSPaths, cls).__classcall__(cls, starting_weight)
Example #5
0
    def __classcall_private__(cls, crystals, weight):
        """
        Normalize input to ensure a unique representation.

        EXAMPLES::

            sage: B = crystals.KirillovReshetikhin(['A',2,1], 1,1)
            sage: L = RootSystem(['A',2,1]).weight_lattice()
            sage: C = crystals.KyotoPathModel(B, L.fundamental_weight(0))
            sage: C2 = crystals.KyotoPathModel((B,), L.fundamental_weight(0))
            sage: C3 = crystals.KyotoPathModel([B], L.fundamental_weight(0))
            sage: C is C2 and C2 is C3
            True

            sage: L = RootSystem(['A',2,1]).weight_space()
            sage: C = KyotoPathModel(B, L.fundamental_weight(0))
            Traceback (most recent call last):
            ...
            ValueError: Lambda[0] is not in the weight lattice
        """
        if isinstance(crystals, list):
            crystals = tuple(crystals)
        elif not isinstance(crystals, tuple):
            crystals = (crystals, )

        if any(not B.is_perfect() for B in crystals):
            raise ValueError("all crystals must be perfect")
        level = crystals[0].level()
        if any(B.level() != level for B in crystals[1:]):
            raise ValueError("all crystals must have the same level")
        ct = crystals[0].cartan_type()
        P = RootSystem(ct).weight_lattice()
        if weight.parent() is not P:
            raise ValueError("{} is not in the weight lattice".format(weight))
        if sum(ct.dual().c()[i] * weight.scalar(h)
               for i, h in enumerate(P.simple_coroots())) != level:
            raise ValueError("{} is not a level {} weight".format(
                weight, level))

        return super(KyotoPathModel, cls).__classcall__(cls, crystals, weight)
Example #6
0
    def __init__(self, cartan_type, highest_weight):
        """
        EXAMPLES::

            sage: C = ClassicalCrystalOfAlcovePaths(['A',3],[1,0,0])
            sage: C.list()
            [[], [0], [0, 1], [0, 1, 2]]
            sage: TestSuite(C).run()
        """
        Parent.__init__(self, category=ClassicalCrystals())
        self._cartan_type = CartanType(cartan_type)
        self._name = "The crystal of alcove paths for type %s" % cartan_type
        self.chain_cache = {}
        self.endweight_cache = {}

        self.R = RootSystem(cartan_type)
        alpha = self.R.root_space().simple_roots()
        Lambda = self.R.weight_space().basis()

        self.positive_roots = sorted(self.R.root_space().positive_roots())

        self.weight = Lambda[Integer(1)] - Lambda[Integer(1)]
        offset = self.R.index_set()[Integer(0)]
        for j in self.R.index_set():
            self.weight = self.weight + highest_weight[j - offset] * Lambda[j]

        self.initial_element = self([])

        self.initial_element.chain = self.get_initial_chain(self.weight)
        rho = (Integer(1) / Integer(2)) * sum(self.positive_roots)
        self.initial_element.endweight = rho

        self.chain_cache[str([])] = self.initial_element.chain
        self.endweight_cache[str([])] = self.initial_element.endweight

        self.module_generators = [self.initial_element]

        self._list = super(ClassicalCrystalOfAlcovePaths, self).list()
        self._digraph = super(ClassicalCrystalOfAlcovePaths, self).digraph()
        self._digraph_closure = self.digraph().transitive_closure()
    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
Example #8
0
    def __classcall_private__(cls, cartan_type, La):
        r"""
        Normalize input to ensure a unique representation.

        INPUT:

        - ``ct`` -- Cartan type

        - ``La`` -- an element of ``weight_lattice``

        EXAMPLES::

            sage: La = RootSystem(['E',8,1]).weight_lattice().fundamental_weights()
            sage: M = CrystalOfNakajimaMonomials(['E',8,1],La[0]+La[8])
            sage: M1 = CrystalOfNakajimaMonomials(CartanType(['E',8,1]),La[0]+La[8])
            sage: M2 = CrystalOfNakajimaMonomials(['E',8,1],M.Lambda()[0] + M.Lambda()[8])
            sage: M is M1 is M2
            True
        """
        cartan_type = CartanType(cartan_type)
        La = RootSystem(cartan_type).weight_lattice()(La)
        return super(CrystalOfNakajimaMonomials,
                     cls).__classcall__(cls, cartan_type, La)
    def __init__(self,
                 abstract_polynomial_ring,
                 group_code,
                 group_type,
                 basis_name,
                 basis_repr=None,
                 extra_category=None):
        r"""
        TESTS::

            sage: # Fix a nice test
        """
        if (basis_repr is None):
            basis_repr = abstract_polynomial_ring._main_repr_var
        self._root_system = RootSystem(group_code)
        self._group_type = group_type
        self._basis_keys = MonomialKeyWrapper(self._root_system)
        FiniteRankPolynomialRingWithBasis.__init__(
            self,
            abstract_polynomial_ring,
            abstract_polynomial_ring.polynomial_ring_tower(
            ).monomial_basis_with_type(group_type),
            self._basis_keys,
            basis_name,
            basis_repr,
            extra_category=extra_category)

        monomial_basis = self.abstract_algebra().monomial_basis()
        self._to_monomial_morphism = self._module_morphism(
            self._to_monomial_on_basis, codomain=monomial_basis)
        self._from_monomial_morphism = monomial_basis._module_morphism(
            self._from_monomial_on_basis, codomain=self)

        #temp#
        self._to_monomial_morphism.register_as_coercion()
        self._from_monomial_morphism.register_as_coercion()
    def __init__(self, cartan_type, prefix, finite=True):
        r"""

        EXAMPLES::

            sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup
            sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',3,1])
            sage: F in Groups().Commutative().Finite()
            True
            sage: TestSuite(F).run()
        """
        def leading_support(beta):
            r"""
            Given a dictionary with one key, return this key
            """
            supp = beta.support()
            assert len(supp) == 1
            return supp[0]

        self._cartan_type = cartan_type
        self._prefix = prefix
        special_node = cartan_type.special_node()
        self._special_nodes = cartan_type.special_nodes()

        # initialize dictionaries with the entries for the
        # distinguished special node

        # dictionary of inverse elements
        inverse_dict = {}
        inverse_dict[special_node] = special_node
        # dictionary for the action of special automorphisms by
        # permutations of the affine Dynkin nodes
        auto_dict = {}
        for i in cartan_type.index_set():
            auto_dict[special_node, i] = i
        # dictionary for the finite Weyl component of the special automorphisms
        reduced_words_dict = {}
        reduced_words_dict[0] = tuple([])

        if cartan_type.dual().is_untwisted_affine():
            # this combines the computations for an untwisted affine
            # type and its affine dual
            cartan_type = cartan_type.dual()
        if cartan_type.is_untwisted_affine():
            cartan_type_classical = cartan_type.classical()
            I = [i for i in cartan_type_classical.index_set()]
            Q = RootSystem(cartan_type_classical).root_lattice()
            alpha = Q.simple_roots()
            omega = RootSystem(
                cartan_type_classical).weight_lattice().fundamental_weights()
            W = Q.weyl_group(prefix="s")
            for i in self._special_nodes:
                if i == special_node:
                    continue
                antidominant_weight, reduced_word = omega[
                    i].to_dominant_chamber(reduced_word=True, positive=False)
                reduced_words_dict[i] = tuple(reduced_word)
                w0i = W.from_reduced_word(reduced_word)
                idual = leading_support(-antidominant_weight)
                inverse_dict[i] = idual
                auto_dict[i, special_node] = i
                for j in I:
                    if j == idual:
                        auto_dict[i, j] = special_node
                    else:
                        auto_dict[i, j] = leading_support(w0i.action(alpha[j]))

        self._action = Family(
            self._special_nodes, lambda i: Family(cartan_type.index_set(),
                                                  lambda j: auto_dict[i, j]))
        self._dual_node = Family(self._special_nodes, inverse_dict.__getitem__)
        self._reduced_words = Family(self._special_nodes,
                                     reduced_words_dict.__getitem__)

        if finite:
            cat = Category.join(
                (Groups().Commutative().Finite(), EnumeratedSets()))
        else:
            cat = Groups().Commutative().Infinite()
        Parent.__init__(self, category=cat)
Example #11
0
        def energy_function(self):
            r"""
            Return the energy function of ``self``.

            The energy function `D(\pi)` of the level zero LS path `\pi \in \mathbb{B}_\mathrm{cl}(\lambda)`
            requires a series of definitions; for simplicity the root system is assumed to be untwisted affine.

            The LS path `\pi` is a piecewise linear map from the unit interval `[0,1]` to the weight lattice.
            It is specified by "times" `0=\sigma_0<\sigma_1<\dotsm<\sigma_s=1` and "direction vectors"
            `x_u \lambda` where `x_u \in W/W_J` for `1\le u\le s`, and `W_J` is the
            stabilizer of `\lambda` in the finite Weyl group `W`. Precisely,

            .. MATH::

                \pi(t)=\sum_{u'=1}^{u-1} (\sigma_{u'}-\sigma_{u'-1})x_{u'}\lambda+(t-\sigma_{u-1})x_{u}\lambda

            for `1\le u\le s` and `\sigma_{u-1} \le t \le \sigma_{u}`.

            For any `x,y\in W/W_J` let

            .. MATH::

                d: x= w_{0} \stackrel{\beta_{1}}{\leftarrow}
                w_{1} \stackrel{\beta_{2}}{\leftarrow} \cdots
                \stackrel{\beta_{n}}{\leftarrow} w_{n}=y

            be a shortest directed path in the parabolic quantum Bruhat graph. Define

            .. MATH::

                \mathrm{wt}(d):=\sum_{\substack{1\le k\le n \\  \ell(w_{k-1})<\ell(w_k)}}
                \beta_{k}^{\vee}

            It can be shown that `\mathrm{wt}(d)` depends only on `x,y`;
            call its value `\mathrm{wt}(x,y)`. The energy function `D(\pi)` is defined by

            .. MATH::

                D(\pi)=-\sum_{u=1}^{s-1} (1-\sigma_{u}) \langle \lambda,\mathrm{wt}(x_u,x_{u+1}) \rangle

            For more information, see [LNSSS2013]_.

            REFERENCES:

            .. [LNSSS2013] C. Lenart, S. Naito, D. Sagaki, A. Schilling, M. Shimozono,
               A uniform model for Kirillov-Reshetikhin crystals. Extended abstract.
               DMTCS proc, to appear ( {{{:arXiv:`1211.6019`}}} )

            .. NOTE::

                In the dual-of-untwisted case the parabolic quantum Bruhat graph that is used is obtained by
                exchanging the roles of roots and coroots. Moreover, in the computation of the
                pairing the short roots must be doubled (or tripled for type `G`). This factor
                is determined by the translation factor of the corresponding root.
                Type `BC` is viewed as untwisted type, whereas the dual of `BC` is viewed as twisted.
                Except for the untwisted cases, these formulas are currently still conjectural.

            EXAMPLES::

                sage: R = RootSystem(['C',3,1])
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(La[1]+La[3])
                sage: b = LS.module_generators[0]
                sage: c = b.f(1).f(3).f(2)
                sage: c.energy_function()
                0
                sage: c=b.e(0)
                sage: c.energy_function()
                1

                sage: R = RootSystem(['A',2,1])
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(2*La[1])
                sage: b = LS.module_generators[0]
                sage: c = b.e(0)
                sage: c.energy_function()
                1
                sage: [c.energy_function() for c in sorted(LS.list())]
                [0, 1, 0, 0, 0, 1, 0, 1, 0]

            The next test checks that the energy function is constant on classically connected components::

                sage: R = RootSystem(['A',2,1])
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(2*La[1]+La[2])
                sage: G = LS.digraph(index_set=[1,2])
                sage: C = G.connected_components()
                sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
                [True, True, True, True]

                sage: R = RootSystem(['D',4,2])
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(La[2])
                sage: J = R.cartan_type().classical().index_set()
                sage: hw = [x for x in LS if x.is_highest_weight(J)]
                sage: [(x.weight(), x.energy_function()) for x in hw]
                [(-2*Lambda[0] + Lambda[2], 0), (-2*Lambda[0] + Lambda[1], 1), (0, 2)]
                sage: G = LS.digraph(index_set=J)
                sage: C = G.connected_components()
                sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
                [True, True, True]

                sage: R = RootSystem(CartanType(['G',2,1]).dual())
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(La[1]+La[2])
                sage: G = LS.digraph(index_set=[1,2])
                sage: C = G.connected_components()
                sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
                [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]

                sage: ct = CartanType(['BC',2,2]).dual()
                sage: R = RootSystem(ct)
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(2*La[1]+La[2])
                sage: G = LS.digraph(index_set=R.cartan_type().classical().index_set())
                sage: C = G.connected_components()
                sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
                [True, True, True, True, True, True, True, True, True, True, True]

                sage: R = RootSystem(['BC',2,2])
                sage: La = R.weight_space().basis()
                sage: LS = CrystalOfProjectedLevelZeroLSPaths(2*La[1]+La[2])
                sage: G = LS.digraph(index_set=R.cartan_type().classical().index_set())
                sage: C = G.connected_components()
                sage: [all(c[0].energy_function()==a.energy_function() for a in c) for c in C]
                [True, True, True, True, True, True, True, True, True, True, True, True, True, True, True,
                True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
            """
            weight = self.parent().weight
            P = weight.parent()
            c_weight = P.classical()(weight)
            ct = P.cartan_type()
            cartan = ct.classical()
            Qv = RootSystem(cartan).coroot_lattice()
            W = WeylGroup(cartan,prefix='s')
            J = tuple(weight.weyl_stabilizer())
            L = self.weyl_group_representation()
            if ct.is_untwisted_affine() or ct.type() == 'BC':
                untwisted = True
                G = W.quantum_bruhat_graph(J)
            else:
                untwisted = False
                cartan_dual = cartan.dual()
                Wd = WeylGroup(cartan_dual, prefix='s')
                G = Wd.quantum_bruhat_graph(J)
                Qd = RootSystem(cartan_dual).root_lattice()
                dualize = lambda x: Qv.from_vector(x.to_vector())
                L = [Wd.from_reduced_word(x.reduced_word()) for x in L]
                def stretch_short_root(a):
                    # stretches roots by translation factor
                    if ct.dual().type() == 'BC':
                        return ct.c()[a.to_simple_root()]*a
                    return ct.dual().c()[a.to_simple_root()]*a
                    #if a.is_short_root():
                    #    if cartan_dual.type() == 'G':
                    #        return 3*a
                    #    else:
                    #        return 2*a
                    #return a
            paths = [G.shortest_path(L[i+1],L[i]) for i in range(len(L)-1)]
            paths_labels = [[G.edge_label(p[i],p[i+1]) for i in range(len(p)-1) if p[i].length()+1 != p[i+1].length()] for p in paths]
            scalars = self.scalar_factors()
            if untwisted:
                s = sum((1-scalars[i])*c_weight.scalar( Qv.sum(root.associated_coroot()
                       for root in paths_labels[i]) ) for i in range(len(paths_labels)))
                if ct.type() == 'BC':
                    return 2*s
                else:
                    return s
            else:
                s = sum((1-scalars[i])*c_weight.scalar( dualize (Qd.sum(stretch_short_root(root) for root in paths_labels[i])) ) for i in range(len(paths_labels)))
                if ct.dual().type() == 'BC':
                    return s/2
                else:
                    return s
Example #12
0
    def Shi(self, data, K=QQ, names=None, m=1):
        r"""
        Return the Shi arrangement.

        INPUT:

        - ``data`` -- either an integer or a Cartan type (or coercible
          into; see "CartanType")

        - ``K`` -- field (default:``QQ``)

        - ``names`` -- tuple of strings or ``None`` (default); the
          variable names for the ambient space

        - ``m`` -- integer (default: 1)

        OUTPUT:

        - If ``data`` is an integer `n`, return the Shi arrangement in
          dimension `n`, i.e. the set of `n(n-1)` hyperplanes:
          `\{ x_i - x_j = 0,1 : 1 \leq i \leq j \leq n \}`. This corresponds
          to the Shi arrangement of Cartan type `A_{n-1}`.

        - If ``data`` is a Cartan type, return the Shi arrangement of given
          type.

        - If `m > 1`, return the `m`-extended Shi arrangement of given type.

        The `m`-extended Shi arrangement of a given crystallographic
        Cartan type is defined by the inner product
        `\langle a,x \rangle = k` for `-m < k \leq m` and
        `a \in \Phi^+` is a positive root of the root system `\Phi`.

        EXAMPLES::

            sage: hyperplane_arrangements.Shi(4)
            Arrangement of 12 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("A3")
            Arrangement of 12 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("A3",m=2)
            Arrangement of 24 hyperplanes of dimension 4 and rank 3
            sage: hyperplane_arrangements.Shi("B4")
            Arrangement of 32 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("B4",m=3)
            Arrangement of 96 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("C3")
            Arrangement of 18 hyperplanes of dimension 3 and rank 3
            sage: hyperplane_arrangements.Shi("D4",m=3)
            Arrangement of 72 hyperplanes of dimension 4 and rank 4
            sage: hyperplane_arrangements.Shi("E6")
            Arrangement of 72 hyperplanes of dimension 8 and rank 6
            sage: hyperplane_arrangements.Shi("E6",m=2)
            Arrangement of 144 hyperplanes of dimension 8 and rank 6

        If the Cartan type is not crystallographic, the Shi arrangement
        is not defined::

            sage: hyperplane_arrangements.Shi("H4")
            Traceback (most recent call last):
            ...
            NotImplementedError: Shi arrangements are not defined for non crystallographic Cartan types

        The characteristic polynomial is pre-computed using the results
        of [Ath1996]_::

            sage: hyperplane_arrangements.Shi("A3").characteristic_polynomial()
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: hyperplane_arrangements.Shi("A3",m=2).characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: hyperplane_arrangements.Shi("C3").characteristic_polynomial()
            x^3 - 18*x^2 + 108*x - 216
            sage: hyperplane_arrangements.Shi("E6").characteristic_polynomial()
            x^8 - 72*x^7 + 2160*x^6 - 34560*x^5 + 311040*x^4 - 1492992*x^3 + 2985984*x^2
            sage: hyperplane_arrangements.Shi("B4",m=3).characteristic_polynomial()
            x^4 - 96*x^3 + 3456*x^2 - 55296*x + 331776

        TESTS::

            sage: h = hyperplane_arrangements.Shi(4)
            sage: h.characteristic_polynomial()
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: h.characteristic_polynomial.clear_cache()  # long time
            sage: h.characteristic_polynomial()              # long time
            x^4 - 12*x^3 + 48*x^2 - 64*x
            sage: h = hyperplane_arrangements.Shi("A3",m=2)
            sage: h.characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: h.characteristic_polynomial.clear_cache()
            sage: h.characteristic_polynomial()
            x^4 - 24*x^3 + 192*x^2 - 512*x
            sage: h = hyperplane_arrangements.Shi("B3",m=3)
            sage: h.characteristic_polynomial()
            x^3 - 54*x^2 + 972*x - 5832
            sage: h.characteristic_polynomial.clear_cache()
            sage: h.characteristic_polynomial()
            x^3 - 54*x^2 + 972*x - 5832
        """
        if data in NN:
            cartan_type = CartanType(["A", data - 1])
        else:
            cartan_type = CartanType(data)
        if not cartan_type.is_crystallographic():
            raise NotImplementedError(
                "Shi arrangements are not defined for non crystallographic Cartan types"
            )
        n = cartan_type.rank()
        h = cartan_type.coxeter_number()
        Ra = RootSystem(cartan_type).ambient_space()
        PR = Ra.positive_roots()
        d = Ra.dimension()
        H = make_parent(K, d, names)
        x = H.gens()
        hyperplanes = []

        for a in PR:
            for const in range(-m + 1, m + 1):
                hyperplanes.append(sum(a[j] * x[j] for j in range(d)) - const)
        A = H(*hyperplanes)
        x = polygen(QQ, 'x')
        charpoly = x**(d - n) * (x - m * h)**n
        A.characteristic_polynomial.set_cache(charpoly)
        return A
    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)})
Example #14
0
    def one_dimensional_configuration_sum(self, q=None, group_components=True):
        r"""
        Compute the one-dimensional configuration sum.

        INPUT:

        - ``q`` -- (default: ``None``) a variable or ``None``; if ``None``,
          a variable ``q`` is set in the code
        - ``group_components`` -- (default: ``True``) boolean; if ``True``,
          then the terms are grouped by classical component

        The one-dimensional configuration sum is the sum of the weights of all elements in the crystal
        weighted by the energy function. For untwisted types it uses the parabolic quantum Bruhat graph, see [LNSSS2013]_.
        In the dual-of-untwisted case, the parabolic quantum Bruhat graph is defined by
        exchanging the roles of roots and coroots (which is still conjectural at this point).

        EXAMPLES::

            sage: R = RootSystem(['A',2,1])
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1])
            sage: LS.one_dimensional_configuration_sum() # long time
            B[-2*Lambda[1] + 2*Lambda[2]] + (q+1)*B[-Lambda[1]]
            + (q+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]]
            sage: R.<t> = ZZ[]
            sage: LS.one_dimensional_configuration_sum(t, False) # long time
            B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + (t+1)*B[Lambda[1] - Lambda[2]]
            + B[2*Lambda[1]] + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]]

        TESTS::

            sage: R = RootSystem(['B',3,1])
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2])
            sage: LS.one_dimensional_configuration_sum() == LS.one_dimensional_configuration_sum(group_components=False) # long time
            True
            sage: K1 = crystals.KirillovReshetikhin(['B',3,1],1,1)
            sage: K2 = crystals.KirillovReshetikhin(['B',3,1],2,1)
            sage: T = crystals.TensorProduct(K2,K1)
            sage: T.one_dimensional_configuration_sum() == LS.one_dimensional_configuration_sum() # long time
            True

            sage: R = RootSystem(['D',4,2])
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(La[1]+La[2])
            sage: K1 = crystals.KirillovReshetikhin(['D',4,2],1,1)
            sage: K2 = crystals.KirillovReshetikhin(['D',4,2],2,1)
            sage: T = crystals.TensorProduct(K2,K1)
            sage: T.one_dimensional_configuration_sum() == LS.one_dimensional_configuration_sum() # long time
            True

            sage: R = RootSystem(['A',5,2])
            sage: La = R.weight_space().basis()
            sage: LS = crystals.ProjectedLevelZeroLSPaths(3*La[1])
            sage: K1 = crystals.KirillovReshetikhin(['A',5,2],1,1)
            sage: T = crystals.TensorProduct(K1,K1,K1)
            sage: T.one_dimensional_configuration_sum() == LS.one_dimensional_configuration_sum() # long time
            True
        """
        if q is None:
            from sage.rings.all import QQ
            q = QQ['q'].gens()[0]
        #P0 = self.weight_lattice_realization().classical()
        P0 = RootSystem(self.cartan_type().classical()).weight_lattice()
        B = P0.algebra(q.parent())

        def weight(x):
            w = x.weight()
            return P0.sum(
                int(c) * P0.basis()[i] for i, c in w if i in P0.index_set())

        if group_components:
            G = self.digraph(
                index_set=self.cartan_type().classical().index_set())
            C = G.connected_components()
            return sum(q**(c[0].energy_function()) *
                       B.sum(B(weight(b)) for b in c) for c in C)
        return B.sum(q**(b.energy_function()) * B(weight(b)) for b in self)
Example #15
0
    def __init__(self, starting_weight, starting_weight_parent):
        """
        EXAMPLES::

            sage: C = crystals.LSPaths(['A',2,1],[-1,0,1]); C
            The crystal of LS paths of type ['A', 2, 1] and weight -Lambda[0] + Lambda[2]
            sage: C.R
            Root system of type ['A', 2, 1]
            sage: C.weight
            -Lambda[0] + Lambda[2]
            sage: C.weight.parent()
            Extended weight space over the Rational Field of the Root system of type ['A', 2, 1]
            sage: C.module_generators
            [(-Lambda[0] + Lambda[2],)]

        TESTS::

            sage: C = crystals.LSPaths(['A',2,1], [-1,0,1])
            sage: TestSuite(C).run() # long time
            sage: C = crystals.LSPaths(['E',6], [1,0,0,0,0,0])
            sage: TestSuite(C).run()

            sage: R = RootSystem(['C',3,1])
            sage: La = R.weight_space().basis()
            sage: LaE = R.weight_space(extended=True).basis()
            sage: B = crystals.LSPaths(La[0])
            sage: BE = crystals.LSPaths(LaE[0])
            sage: B is BE
            False
            sage: B.weight_lattice_realization()
            Weight space over the Rational Field of the Root system of type ['C', 3, 1]
            sage: BE.weight_lattice_realization()
            Extended weight space over the Rational Field of the Root system of type ['C', 3, 1]
        """
        cartan_type = starting_weight.parent().cartan_type()
        self.R = RootSystem(cartan_type)
        self.weight = starting_weight
        if not self.weight.parent().base_ring().has_coerce_map_from(QQ):
            raise ValueError(
                "Please use the weight space, rather than weight lattice for your weights"
            )
        self._cartan_type = cartan_type
        self._name = "The crystal of LS paths of type %s and weight %s" % (
            cartan_type, starting_weight)
        if cartan_type.is_affine():
            if all(i >= 0 for i in starting_weight.coefficients()):
                Parent.__init__(self,
                                category=(RegularCrystals(),
                                          HighestWeightCrystals(),
                                          InfiniteEnumeratedSets()))
            elif starting_weight.parent().is_extended():
                Parent.__init__(self,
                                category=(RegularCrystals(),
                                          InfiniteEnumeratedSets()))
            else:
                Parent.__init__(self,
                                category=(RegularCrystals(), FiniteCrystals()))
        else:
            Parent.__init__(self, category=ClassicalCrystals())

        if starting_weight == starting_weight.parent().zero():
            initial_element = self(tuple([]))
        else:
            initial_element = self(tuple([starting_weight]))
        self.module_generators = [initial_element]