Exemple #1
0
    def __classcall_private__(cls,
                              ambient,
                              contained=None,
                              generators=None,
                              virtualization=None,
                              scaling_factors=None,
                              cartan_type=None,
                              index_set=None,
                              category=None):
        """
        Normalize arguments to ensure a (relatively) unique representation.

        EXAMPLES::

            sage: B = crystals.Tableaux(['A',4], shape=[2,1])
            sage: S1 = B.subcrystal(generators=(B(2,1,1), B(5,2,4)), index_set=[1,2])
            sage: S2 = B.subcrystal(generators=[B(2,1,1), B(5,2,4)], cartan_type=['A',4], index_set=(1,2))
            sage: S1 is S2
            True
        """
        if isinstance(contained, (list, tuple, set, frozenset)):
            contained = frozenset(contained)
        #elif contained in Sets():

        if cartan_type is None:
            cartan_type = ambient.cartan_type()
        else:
            cartan_type = CartanType(cartan_type)
        if index_set is None:
            index_set = cartan_type.index_set
        if generators is None:
            generators = ambient.module_generators

        category = Crystals().or_subcategory(category)
        if ambient in FiniteCrystals() or isinstance(contained, frozenset):
            category = category.Finite()

        if virtualization is not None:
            if scaling_factors is None:
                scaling_factors = {i: 1 for i in index_set}
            from sage.combinat.crystals.virtual_crystal import VirtualCrystal
            return VirtualCrystal(ambient, virtualization, scaling_factors,
                                  contained, generators, cartan_type,
                                  index_set, category)
        if scaling_factors is not None:
            # virtualization must be None
            virtualization = {i: (i, ) for i in index_set}
            from sage.combinat.crystals.virtual_crystal import VirtualCrystal
            return VirtualCrystal(ambient, virtualization, scaling_factors,
                                  contained, generators, cartan_type,
                                  index_set, category)

        # We need to give these as optional arguments so it unpickles correctly
        return super(Subcrystal, cls).__classcall__(cls,
                                                    ambient,
                                                    contained,
                                                    tuple(generators),
                                                    cartan_type=cartan_type,
                                                    index_set=tuple(index_set),
                                                    category=category)
Exemple #2
0
        def digraph(self, subset=None, index_set=None):
            r"""
            Return the :class:`DiGraph` associated to ``self``.

            INPUT:

            - ``subset`` -- (optional) a subset of vertices for
              which the digraph should be constructed

            - ``index_set`` -- (optional) the index set to draw arrows

            .. SEEALSO::

                :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph`

            EXAMPLES::

                sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
                sage: G = C.digraph()
                sage: G.latex_options()  # optional - dot2tex
                LaTeX options for Digraph on 29 vertices:
                {...'edge_options': <function <lambda> at 0x...>,...}
                sage: view(G, tightpage=True)  # optional - dot2tex graphviz, not tested (opens external window)
            """
            G = Crystals().parent_class.digraph(self, subset, index_set)
            if have_dot2tex():
                f = lambda u_v_label: ({"backward": u_v_label[2] == 0})
                G.set_latex_options(edge_options=f)
            return G
Exemple #3
0
        def digraph(self, subset=None, index_set=None):
            r"""
            Return the :class:`DiGraph` associated to ``self``.

            INPUT:

            - ``subset`` -- (optional) a subset of vertices for
              which the digraph should be constructed

            - ``index_set`` -- (optional) the index set to draw arrows

            .. SEEALSO::

                :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph`

            EXAMPLES::

                sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
                sage: G = C.digraph()
                sage: G.latex_options()  # optional - dot2tex
                LaTeX options for Digraph on 29 vertices:
                {...'edge_options': <function ... at ...>...}
                sage: view(G, tightpage=True)  # optional - dot2tex graphviz, not tested (opens external window)
            """
            G = Crystals().parent_class.digraph(self, subset, index_set)
            if have_dot2tex():
                f = lambda u_v_label: ({"backward": u_v_label[2] == 0})
                G.set_latex_options(edge_options=f)
            return G
Exemple #4
0
    def __classcall_private__(cls,
                              ambient,
                              virtualization,
                              scaling_factors,
                              contained=None,
                              generators=None,
                              cartan_type=None,
                              index_set=None,
                              category=None):
        """
        Normalize arguments to ensure a unique representation.

        EXAMPLES::

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: psi1 = B.crystal_morphism(C.module_generators)
            sage: V1 = psi1.image()
            sage: psi2 = B.crystal_morphism(C.module_generators, index_set=[1,2,3])
            sage: V2 = psi2.image()
            sage: V1 is V2
            True

        TESTS:

        Check that :trac:`19481` is fixed::

            sage: from sage.combinat.crystals.virtual_crystal import VirtualCrystal
            sage: A = crystals.Tableaux(['A',3], shape=[2,1,1])
            sage: V = VirtualCrystal(A, {1:(1,3), 2:(2,)}, {1:1, 2:2}, cartan_type=['C',2])
            sage: V.category()
            Category of finite crystals
        """
        if cartan_type is None:
            cartan_type = ambient.cartan_type()
        else:
            cartan_type = CartanType(cartan_type)
        if index_set is None:
            index_set = cartan_type.index_set()
        if generators is None:
            generators = ambient.module_generators
        virtualization = Family(virtualization)
        scaling_factors = Family(scaling_factors)

        category = Crystals().or_subcategory(category)
        if ambient in FiniteCrystals() or isinstance(contained, frozenset):
            category = category.Finite()

        return super(Subcrystal,
                     cls).__classcall__(cls, ambient, virtualization,
                                        scaling_factors, contained,
                                        tuple(generators), cartan_type,
                                        tuple(index_set), category)
        def _Hom_(self, Y, category=None, **options):
            r"""
            Return the homset from ``self`` to ``Y`` in the
            category ``category``.

            INPUT:

            - ``Y`` -- a crystal
            - ``category`` -- a subcategory of :class:`HighestWeightCrysals`()
              or ``None``

            The sole purpose of this method is to construct the homset as a
            :class:`~sage.categories.highest_weight_crystals.HighestWeightCrystalHomset`.
            If ``category`` is specified and is not a subcategory of
            :class:`HighestWeightCrystals`, a ``TypeError`` is raised instead

            This method is not meant to be called directly. Please use
            :func:`sage.categories.homset.Hom` instead.

            EXAMPLES::

                sage: B = crystals.Tableaux(['A',2], shape=[2,1])
                sage: H = B._Hom_(B)
                sage: H
                Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                 to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                sage: type(H)
                <class 'sage.categories.highest_weight_crystals.HighestWeightCrystalHomset_with_category'>

            TESTS:

            Check that we fallback first to trying a crystal homset
            (:trac:`19458`)::

                sage: Binf = crystals.infinity.Tableaux(['A',2])
                sage: Bi = crystals.elementary.Elementary(Binf.cartan_type(), 1)
                sage: tens = Bi.tensor(Binf)
                sage: Hom(Binf, tens)
                Set of Crystal Morphisms from ...
            """
            if category is None:
                category = self.category()
            elif not category.is_subcategory(Crystals()):
                raise TypeError(
                    "{} is not a subcategory of Crystals()".format(category))
            if Y not in Crystals():
                raise TypeError("{} is not a crystal".format(Y))
            return HighestWeightCrystalHomset(self,
                                              Y,
                                              category=category,
                                              **options)
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: HighestWeightCrystals().super_categories()
            [Category of crystals]
        """
        return [Crystals()]
Exemple #7
0
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: FiniteCrystals().super_categories()
            [Category of crystals, Category of finite enumerated sets]
        """
        return [Crystals(), FiniteEnumeratedSets()]
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: RegularCrystals().super_categories()
            [Category of crystals]
        """
        return [Crystals()]
Exemple #9
0
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: from sage.categories.loop_crystals import LoopCrystals
            sage: LoopCrystals().super_categories()
            [Category of crystals]
        """
        return [Crystals()]
Exemple #10
0
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: from sage.categories.regular_supercrystals import RegularSuperCrystals
            sage: C = RegularSuperCrystals()
            sage: C.super_categories()
            [Category of finite crystals]
        """
        return [Crystals().Finite()]
Exemple #11
0
    def super_categories(self):
        r"""
        EXAMPLES::

            sage: from sage.categories.supercrystals import SuperCrystals
            sage: C = SuperCrystals()
            sage: C.super_categories()
            [Category of crystals]
        """
        return [Crystals()]
Exemple #12
0
    def example(self, n=3):
        """
        Returns an example of highest weight crystals, as per
        :meth:`Category.example`.

        EXAMPLES::

            sage: B = ClassicalCrystals().example(); B
            Highest weight crystal of type A_3 of highest weight omega_1
        """
        return Crystals().example(n)
Exemple #13
0
    def example(self, n=3):
        """
        Returns an example of highest weight crystals, as per
        :meth:`Category.example`.

        EXAMPLES::

            sage: B = FiniteCrystals().example(); B
            Highest weight crystal of type A_3 of highest weight omega_1
        """
        from sage.categories.crystals import Crystals
        return Crystals().example(n)
    def __init__(self, cartan_type, i):
        r"""
        Initialize ``self``.

        EXAMPLES::

            sage: B = crystals.elementary.Elementary("D4",3)
            sage: TestSuite(B).run()
        """
        Parent.__init__(self, category=(Crystals(), InfiniteEnumeratedSets()))
        self._i = i
        self._cartan_type = cartan_type
        self.module_generators = (self.element_class(self, 0), )
Exemple #15
0
        def _test_fast_iter(self, **options):
            r"""
            Tests whether the elements returned by :meth:`.__iter__`
            and ``Crystal.list(self)`` are the same (the two
            algorithms are different).

            EXAMPLES::

                sage: C = crystals.Letters(['A', 5])
                sage: C._test_fast_iter()
            """
            tester = self._tester(**options)
            S = list(self)
            SS = list(Crystals().parent_class.__iter__(self))
            tester.assert_(len(S) == len(SS))
            tester.assert_(len(S) == len(set(S)))
            tester.assert_(set(S) == set(SS))
Exemple #16
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]
Exemple #17
0
    def __init__(self, R, C, q):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: from sage.algebras.quantum_groups.representations import MinusculeRepresentation
            sage: C = crystals.Tableaux(['A',3], shape=[1,1])
            sage: R = ZZ['q'].fraction_field()
            sage: V = MinusculeRepresentation(R, C)
            sage: TestSuite(V).run()
        """
        self._q = q
        self._d = C.cartan_type().symmetrizer()
        cat = QuantumGroupRepresentations(R).WithBasis()
        if C in Crystals().Finite():
            cat = cat.FiniteDimensional()
        CombinatorialFreeModule.__init__(self, R, C, category=cat)
Exemple #18
0
    def __classcall_private__(cls,
                              ambient,
                              virtualization,
                              scaling_factors,
                              contained=None,
                              generators=None,
                              cartan_type=None,
                              index_set=None,
                              category=None):
        """
        Normalize arguments to ensure a unique representation.

        EXAMPLES::

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: psi1 = B.crystal_morphism(C.module_generators)
            sage: V1 = psi1.image()
            sage: psi2 = B.crystal_morphism(C.module_generators, index_set=[1,2,3])
            sage: V2 = psi2.image()
            sage: V1 is V2
            True
        """
        if cartan_type is None:
            cartan_type = ambient.cartan_type()
        else:
            cartan_type = CartanType(cartan_type)
        if index_set is None:
            index_set = cartan_type.index_set()
        if generators is None:
            generators = ambient.module_generators
        virtualization = Family(virtualization)
        scaling_factors = Family(scaling_factors)

        category = Crystals().or_subcategory(category)

        return super(Subcrystal,
                     cls).__classcall__(cls, ambient, virtualization,
                                        scaling_factors, contained,
                                        tuple(generators), cartan_type,
                                        tuple(index_set), category)
Exemple #19
0
        def _Hom_(self, Y, category=None, **options):
            r"""
            Return the homset from ``self`` to ``Y`` in the
            category ``category``.

            INPUT:

            - ``Y`` -- a crystal
            - ``category`` -- a subcategory of :class:`HighestWeightCrysals`()
              or ``None``

            The sole purpose of this method is to construct the homset as a
            :class:`~sage.categories.highest_weight_crystals.HighestWeightCrystalHomset`.
            If ``category`` is specified and is not a subcategory of
            :class:`HighestWeightCrystals`, a ``TypeError`` is raised instead

            This method is not meant to be called directly. Please use
            :func:`sage.categories.homset.Hom` instead.

            EXAMPLES::

                sage: B = crystals.Tableaux(['A',2], shape=[2,1])
                sage: H = B._Hom_(B)
                sage: H
                Set of Crystal Morphisms from The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                 to The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
                sage: type(H)
                <class 'sage.categories.highest_weight_crystals.HighestWeightCrystalHomset_with_category'>
            """
            if category is None:
                category = self.category()
            elif not category.is_subcategory(HighestWeightCrystals()):
                raise TypeError(
                    "{} is not a subcategory of HighestWeightCrystals()".
                    format(category))
            if Y not in Crystals():
                raise TypeError("{} is not a crystal".format(Y))
            return HighestWeightCrystalHomset(self,
                                              Y,
                                              category=category,
                                              **options)
Exemple #20
0
        def digraph(self, subset=None, index_set=None, depth=None):
            """
            Return the DiGraph associated to ``self``.

            INPUT:

            - ``subset`` -- (optional) a subset of vertices for
              which the digraph should be constructed

            - ``index_set`` -- (optional) the index set to draw arrows

            - ``depth`` -- the depth to draw; optional only for finite crystals

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',2], shape=[2,1])
                sage: T.digraph()
                Digraph on 8 vertices
                sage: S = T.subcrystal(max_depth=2)
                sage: len(S)
                5
                sage: G = T.digraph(subset=list(S))
                sage: G.is_isomorphic(T.digraph(depth=2), edge_labels=True)
                True

            TESTS:

            The following example demonstrates the speed improvement.
            The speedup in non-affine types is small however::

                sage: depth = 5
                sage: C = crystals.AlcovePaths(['A',2,1], [1,1,0])
                sage: general_digraph = Crystals().parent_class.digraph
                sage: S = C.subcrystal(max_depth=depth, direction='lower')
                sage: %timeit C.digraph(depth=depth) # not tested
                10 loops, best of 3: 48.9 ms per loop
                sage: %timeit general_digraph(C, subset=S) # not tested
                10 loops, best of 3: 96.5 ms per loop
                sage: G1 = C.digraph(depth=depth)
                sage: G2 = general_digraph(C, subset=S)
                sage: G1.is_isomorphic(G2, edge_labels=True)
                True
            """
            if subset is not None:
                return Crystals().parent_class.digraph(self, subset, index_set)

            if self not in Crystals().Finite() and depth is None:
                raise NotImplementedError(
                    "crystals not known to be finite must"
                    " specify either the subset or depth")

            from sage.graphs.all import DiGraph
            if index_set is None:
                index_set = self.index_set()

            rank = 0
            d = {g: {} for g in self.module_generators}
            visited = set(d.keys())

            while depth is None or rank < depth:
                recently_visited = set()
                for x in visited:
                    d.setdefault(x, {})  # does nothing if there's a default
                    for i in index_set:
                        xfi = x.f(i)
                        if xfi is not None:
                            d[x][xfi] = i
                            recently_visited.add(xfi)
                if not recently_visited:  # No new nodes, nothing more to do
                    break
                rank += 1
                visited = recently_visited

            G = DiGraph(d)
            if have_dot2tex():
                G.set_latex_options(
                    format="dot2tex",
                    edge_labels=True,
                    color_by_label=self.cartan_type()._index_set_coloring)
            return G