Example #1
0
        def _latex_(self, **options):
            r"""
            Returns the crystal graph as a latex string. This can be exported
            to a file with self.latex_file('filename').
            
            EXAMPLES::
 
                sage: T = CrystalOfTableaux(['A',2],shape=[1])
                sage: T._latex_()   #optional - dot2tex
                ...
                sage: view(T, pdflatex = True, tightpage = True) #optional - dot2tex graphviz

            One can for example also color the edges using the following options::

                sage: T = CrystalOfTableaux(['A',2],shape=[1])
                sage: T._latex_(color_by_label = {0:"black", 1:"red", 2:"blue"})   #optional - dot2tex graphviz
                ...
            """
            if not have_dot2tex():
                print "dot2tex not available.  Install after running \'sage -sh\'"
                return
            G=self.digraph()
            G.set_latex_options(format="dot2tex", edge_labels = True, 
                                edge_options = lambda (u,v,label): ({"backward":label ==0}), **options)
            return G._latex_()
Example #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
Example #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
Example #4
0
        def _latex_(self, **options):
            r"""
            Returns the crystal graph as a latex string. This can be exported
            to a file with self.latex_file('filename').
            
            EXAMPLES::
 
                sage: T = CrystalOfTableaux(['A',2],shape=[1])
                sage: T._latex_()   #optional - dot2tex
                ...
                sage: view(T, pdflatex = True, tightpage = True) #optional - dot2tex graphviz

            One can for example also color the edges using the following options::

                sage: T = CrystalOfTableaux(['A',2],shape=[1])
                sage: T._latex_(color_by_label = {0:"black", 1:"red", 2:"blue"})   #optional - dot2tex graphviz
                ...
            """
            if not have_dot2tex():
                print "dot2tex not available.  Install after running \'sage -sh\'"
                return
            G=self.digraph()
            G.set_latex_options(format="dot2tex", edge_labels = True, 
                                edge_options = lambda (u,v,label): ({"backward":label ==0}), **options)
            return G._latex_()
Example #5
0
        def digraph(self):
            """
            Returns the DiGraph associated to self.

            EXAMPLES::

                sage: C = Crystals().example(5)
                sage: C.digraph()
                Digraph on 6 vertices

            The edges of the crystal graph are by default colored using blue for edge 1, red for edge 2,
            and green for edge 3::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            One may also overwrite the colors::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Or one may add colors to yet unspecified edges::

                sage: C = Crystals().example(4)
                sage: G = C.digraph()
                sage: C.cartan_type()._index_set_coloring[4]="purple"
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            TODO: add more tests
            """
            from sage.graphs.all import DiGraph
            d = {}
            for x in self:
                d[x] = {}
                for i in self.index_set():
                    child = x.f(i)
                    if child is None:
                        continue
                    d[x][child]=i
            G = DiGraph(d)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = self.cartan_type()._index_set_coloring,
                                    edge_options = lambda (u,v,label): ({"backward":label ==0}))
            return G
Example #6
0
        def digraph(self):
            """
            Returns the DiGraph associated to self.

            EXAMPLES::

                sage: C = Crystals().example(5)
                sage: C.digraph()
                Digraph on 6 vertices

            The edges of the crystal graph are by default colored using blue for edge 1, red for edge 2,
            and green for edge 3::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            One may also overwrite the colors::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Or one may add colors to yet unspecified edges::

                sage: C = Crystals().example(4)
                sage: G = C.digraph()
                sage: C.cartan_type()._index_set_coloring[4]="purple"
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            TODO: add more tests
            """
            from sage.graphs.all import DiGraph
            d = {}
            for x in self:
                d[x] = {}
                for i in self.index_set():
                    child = x.f(i)
                    if child is None:
                        continue
                    d[x][child]=i
            G = DiGraph(d)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = self.cartan_type()._index_set_coloring,
                                    edge_options = lambda (u,v,label): ({"backward":label ==0}))
            return G
Example #7
0
    def digraph(self, subset=None, index_set=None):
        """
        Return the DiGraph associated with ``self``. See
        :meth:`~sage.categories.crystals.ParentMethods.digraph()` for more
        information.

        EXAMPLES::

            sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization()
            sage: S = A.subcrystal(max_depth=3)
            sage: G = A.digraph(subset=S)
        """
        G = super(AffinizationOfCrystal, self).digraph(subset, index_set)
        from sage.graphs.dot2tex_utils import have_dot2tex
        if have_dot2tex():
            G.set_latex_options(edge_options = lambda (u,v,label): ({}))
        return G
Example #8
0
    def digraph(self, subset=None, index_set=None):
        """
        Return the DiGraph associated with ``self``. See
        :meth:`~sage.categories.crystals.ParentMethods.digraph()` for more
        information.

        EXAMPLES::

            sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization()
            sage: S = A.subcrystal(max_depth=3)
            sage: G = A.digraph(subset=S)
        """
        G = super(AffinizationOfCrystal, self).digraph(subset, index_set)
        from sage.graphs.dot2tex_utils import have_dot2tex
        if have_dot2tex():
            G.set_latex_options(edge_options=lambda (u, v, label): ({}))
        return G
Example #9
0
    def _latex_(self, **options):
        r"""
        Return a latex representation of this Kleber tree.
        
        EXAMPLES::
        
            sage: KT = KleberTree(['D', 3], [[2,1], [2,1]])
            sage: KT._latex_()   #optional - dot2tex
            ...
            sage: view(KT, pdflatex=True, tightpage=True) #optional - dot2tex graphviz

        """
        if not have_dot2tex():
            print "dot2tex not available.  Install after running \'sage -sh\'"
            return
        G = self.digraph()
        G.set_latex_options(format="dot2tex", edge_labels=True, **options)
        return G._latex_()
Example #10
0
    def _latex_(self, **options):
        r"""
        Return a latex representation of this Kleber tree.

        EXAMPLES::

            sage: KT = KleberTree(['D', 3], [[2,1], [2,1]])
            sage: KT._latex_()   #optional - dot2tex
            ...
            sage: view(KT, pdflatex=True, tightpage=True) #optional - dot2tex graphviz

        """
        if not have_dot2tex():
            print "dot2tex not available.  Install after running \'sage -sh\'"
            return
        G = self.digraph()
        G.set_latex_options(format="dot2tex", edge_labels=True, **options)
        return G._latex_()
Example #11
0
    def digraph(self):
        r"""
        Return a DiGraph representation of this Kleber tree.

        EXAMPLES::

            sage: KT = KleberTree(['D', 4], [[2, 2]])
            sage: KT.digraph()
            Digraph on 3 vertices
        """
        d = {}
        for x in self:
            d[x] = {}
            if x.parent_node is None:
                continue
            d[x][x.parent_node] = tuple(x.up_root.to_vector())
        G = DiGraph(d)

        if have_dot2tex():
            G.set_latex_options(format="dot2tex", edge_labels=True)
                                # edge_options = lambda (u,v,label): ({"backward":label ==0}))
        return G
Example #12
0
    def digraph(self):
        r"""
        Return a DiGraph representation of this Kleber tree.

        EXAMPLES::

            sage: KT = KleberTree(['D', 4], [[2, 2]])
            sage: KT.digraph()
            Digraph on 3 vertices
        """
        d = {}
        for x in self:
            d[x] = {}
            if x.parent_node is None:
                continue
            d[x][x.parent_node] = tuple(x.up_root.to_vector())
        G = DiGraph(d)

        if have_dot2tex():
            G.set_latex_options(format="dot2tex", edge_labels=True)
            # edge_options = lambda (u,v,label): ({"backward":label ==0}))
        return G
        def _latex_(self, **options):
            r"""
            Returns the crystal graph as a latex string. This can be exported
            to a file with self.latex_file('filename').

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',2],shape=[1])
                sage: T._latex_()   #optional - dot2tex
                '...tikzpicture...'
                sage: view(T, pdflatex = True, tightpage = True) #optional - dot2tex graphviz

            One can for example also color the edges using the following options::

                sage: T = crystals.Tableaux(['A',2],shape=[1])
                sage: T._latex_(color_by_label = {0:"black", 1:"red", 2:"blue"})   #optional - dot2tex graphviz
                '...tikzpicture...'
            """
            if not have_dot2tex():
                print "dot2tex not available.  Install after running \'sage -sh\'"
                return
            G=self.digraph()
            G.set_latex_options(**options)
            return G._latex_()
Example #14
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
Example #15
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 1]])
            sage: x = RC(partition_list=[[1],[1],[1],[1]])
            sage: from sage.combinat.rigged_configurations.bij_type_A import RCToKRTBijectionTypeA
            sage: RCToKRTBijectionTypeA(x).run()
            [[2], [5]]
            sage: bij = RCToKRTBijectionTypeA(x)
            sage: bij.run(build_graph=True)
            [[2], [5]]
            sage: bij._graph
            Digraph on 3 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(
            self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Iterate over each column
            for dummy_var in range(dim[1]):
                # Split off a new column if necessary
                if self.cur_dims[0][1] > 1:
                    if verbose:
                        print("====================")
                        print(
                            repr(self.rigged_con.parent()(
                                *self.cur_partitions,
                                use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying column split")

                    self.cur_dims[0][1] -= 1
                    self.cur_dims.insert(0, [dim[0], 1])

                    # Perform the corresponding splitting map on rigged configurations
                    # All it does is update the vacancy numbers on the RC side
                    for a in range(self.n):
                        self._update_vacancy_numbers(a)

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append(
                            [self._graph[-1][1], (y, len(self._graph)), 'ls'])

                while self.cur_dims[0][0] > 0:
                    if verbose:
                        print("====================")
                        print(
                            repr(self.rigged_con.parent()(
                                *self.cur_partitions,
                                use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")

                    self.cur_dims[0][0] -= 1  # This takes care of the indexing
                    b = self.next_state(self.cur_dims[0][0])

                    # Make sure we have a crystal letter
                    ret_crystal_path[-1].append(letters(b))  # Append the rank

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append([
                            self._graph[-1][1], (y, len(self._graph)),
                            letters(b)
                        ])

                self.cur_dims.pop(0)  # Pop off the leading column

        if build_graph:
            self._graph.pop(0)  # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph)
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex",
                                              edge_labels=True)

        # Basic check to make sure we end with the empty configuration
        #tot_len = sum([len(rp) for rp in self.cur_partitions])
        #if tot_len != 0:
        #    print "Invalid bijection end for:"
        #    print self.rigged_con
        #    print "-----------------------"
        #    print self.cur_partitions
        #    raise ValueError("Invalid bijection end")
        return self.KRT(pathlist=ret_crystal_path)
Example #16
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
Example #17
0
        def dual_equivalence_graph(self, X=None, index_set=None, directed=True):
            r"""
            Return the dual equivalence graph indexed by ``index_set``
            on the subset ``X`` of ``self``.

            Let `b \in B` be an element of weight `0`, so `\varepsilon_j(b)
            = \varphi_j(b)` for all `j \in I`, where `I` is the indexing
            set. We say `b'` is an `i`-elementary dual equivalence
            transformation of `b` (where `i \in I`) if

            * `\varepsilon_i(b) = 1` and `\varepsilon_{i-1}(b) = 0`, and
            * `b' = f_{i-1} f_i e_{i-1} e_i b`.

            We can do the inverse procedure by interchanging `i` and `i-1`
            above.

            .. NOTE::

                If the index set is not an ordered interval, we let
                `i - 1` mean the index appearing before `i` in `I`.

            This definition comes from [Assaf08]_ Section 4 (where our
            `\varphi_j(b)` and `\varepsilon_j(b)` are denoted by
            `\epsilon(b, j)` and `-\delta(b, j)`, respectively).

            The dual equivalence graph of `B` is defined to be the
            colored graph whose vertices are the elements of `B` of
            weight `0`, and whose edges of color `i` (for `i \in I`)
            connect pairs `\{ b, b' \}` such that `b'` is an
            `i`-elementary dual equivalence transformation of `b`.

            .. NOTE::

                This dual equivalence graph is a generalization of
                `\mathcal{G}\left(\mathcal{X}\right)` in [Assaf08]_
                Section 4 except we do not require
                `\varepsilon_i(b) = 0, 1` for all `i`.

            This definition can be generalized by choosing a subset `X`
            of the set of all vertices of `B` of weight `0`, and
            restricting the dual equivalence graph to the vertex set
            `X`.

            INPUT:

            - ``X`` -- (optional) the vertex set `X` (default:
              the whole set of vertices of ``self`` of weight `0`)
            - ``index_set`` -- (optional) the index set `I`
              (default: the whole index set of ``self``); this has
              to be a subset of the index set of ``self`` (as a list
              or tuple)
            - ``directed`` -- (default: ``True``) whether to have the
              dual equivalence graph be directed, where the head of
              an edge `b - b'` is `b` and the tail is
              `b' = f_{i-1} f_i e_{i-1} e_i b`)

            .. SEEALSO::

                :meth:`sage.combinat.partition.Partition.dual_equivalence_graph`

            REFERENCES:

            .. [Assaf08] Sami Assaf. *A combinatorial realization of Schur-Weyl
               duality via crystal graphs and dual equivalence graphs*.
               FPSAC 2008, 141-152, Discrete Math. Theor. Comput. Sci. Proc.,
               AJ, Assoc. Discrete Math. Theor. Comput. Sci., (2008).
               :arxiv:`0804.1587v1`

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',3], shape=[2,2])
                sage: G = T.dual_equivalence_graph()
                sage: sorted(G.edges())
                [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
                 ([[1, 2], [3, 4]], [[1, 3], [2, 4]], 3)]
                sage: T = crystals.Tableaux(['A',4], shape=[3,2])
                sage: G = T.dual_equivalence_graph()
                sage: sorted(G.edges())
                [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
                 ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
                 ([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 3),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
                 ([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 4)]

                sage: T = crystals.Tableaux(['A',4], shape=[3,1])
                sage: G = T.dual_equivalence_graph(index_set=[1,2,3])
                sage: G.vertices()
                [[[1, 3, 4], [2]], [[1, 2, 4], [3]], [[1, 2, 3], [4]]]
                sage: G.edges()
                [([[1, 3, 4], [2]], [[1, 2, 4], [3]], 2),
                 ([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3)]

            TESTS::

                sage: T = crystals.Tableaux(['A',4], shape=[3,1])
                sage: G = T.dual_equivalence_graph(index_set=[2,3])
                sage: sorted(G.edges())
                [([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3),
                 ([[2, 4, 5], [3]], [[2, 3, 5], [4]], 3)]
                sage: sorted(G.vertices())
                [[[1, 3, 4], [2]],
                 [[1, 2, 4], [3]],
                 [[2, 4, 5], [3]],
                 [[1, 2, 3], [4]],
                 [[2, 3, 5], [4]],
                 [[1, 1, 1], [5]],
                 [[1, 1, 5], [5]],
                 [[1, 5, 5], [5]],
                 [[2, 3, 4], [5]]]
            """
            if index_set is None:
                index_set = self.index_set()

            def wt_zero(x):
                for i in index_set:
                    if x.epsilon(i) != x.phi(i):
                        return False
                return True

            if X is None:
                X = [x for x in self if wt_zero(x)]
                checker = lambda x: True
            elif any(not wt_zero(x) for x in X):
                raise ValueError("the elements are not all weight 0")
            else:
                checker = lambda x: x in X

            edges = []
            for x in X:
                for k, i in enumerate(index_set[1:]):
                    im = index_set[k]
                    if x.epsilon(i) == 1 and x.epsilon(im) == 0:
                        y = x.e(i).e(im).f(i).f(im)
                        if checker(y):
                            edges.append([x, y, i])
            from sage.graphs.all import DiGraph
            G = DiGraph([X, edges], format="vertices_and_edges", immutable=True)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex", edge_labels=True,
                                    color_by_label=self.cartan_type()._index_set_coloring)
            return G
Example #18
0
        def dual_equivalence_class(self, index_set=None):
            r"""
            Return the dual equivalence class indexed by ``index_set``
            of ``self``.

            The dual equivalence class of an element `b \in B`
            is the set of all elements of `B` reachable from
            `b` via sequences of `i`-elementary dual equivalence
            relations (i.e., `i`-elementary dual equivalence
            transformations and their inverses) for `i` in the index
            set of `B`.

            For this to be well-defined, the element `b` has to be
            of weight `0` with respect to `I`; that is, we need to have
            `\varepsilon_j(b) = \varphi_j(b)` for all `j \in I`.

            See [Assaf08]_. See also :meth:`dual_equivalence_graph` for
            a definition of `i`-elementary dual equivalence
            transformations.

            INPUT:

            - ``index_set`` -- (optional) the index set `I`
              (default: the whole index set of the crystal); this has
              to be a subset of the index set of the crystal (as a list
              or tuple)

            OUTPUT:

            The dual equivalence class of ``self`` indexed by the
            subset ``index_set``. This class is returned as an
            undirected edge-colored multigraph. The color of an edge
            is the index `i` of the dual equivalence relation it
            encodes.

            .. SEEALSO::

                - :meth:`~sage.categories.regular_crystals.RegularCrystals.ParentMethods.dual_equivalence_graph`
                - :meth:`sage.combinat.partition.Partition.dual_equivalence_graph`

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',3], shape=[2,2])
                sage: G = T(2,1,4,3).dual_equivalence_class()
                sage: sorted(G.edges())
                [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
                 ([[1, 3], [2, 4]], [[1, 2], [3, 4]], 3)]
                sage: T = crystals.Tableaux(['A',4], shape=[3,2])
                sage: G = T(2,1,4,3,5).dual_equivalence_class()
                sage: sorted(G.edges())
                [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 3),
                 ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 4)]
            """
            if index_set is None:
                index_set = self.index_set()

            for i in index_set:
                if self.epsilon(i) != self.phi(i):
                    raise ValueError("the element is not weight 0")

            visited = set([])
            todo = set([self])
            edges = []
            while todo:
                x = todo.pop()
                visited.add(x)
                for k, i in enumerate(index_set[1:]):
                    im = index_set[k]
                    if x.epsilon(i) == 1 and x.epsilon(im) == 0:
                        y = x.e(i).e(im).f(i).f(im)
                        if [y, x, i] not in edges:
                            edges.append([x, y, i])
                        if y not in visited:
                            todo.add(y)
                    if x.epsilon(i) == 0 and x.epsilon(im) == 1:
                        y = x.e(im).e(i).f(im).f(i)
                        if [y, x, i] not in edges:
                            edges.append([x, y, i])
                        if y not in visited:
                            todo.add(y)
            from sage.graphs.graph import Graph
            G = Graph([visited, edges], format="vertices_and_edges",
                      immutable=True, multiedges=True)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex", edge_labels=True,
                                    color_by_label=self.cartan_type()._index_set_coloring)
            return G
Example #19
0
        def dual_equivalence_graph(self,
                                   X=None,
                                   index_set=None,
                                   directed=True):
            r"""
            Return the dual equivalence graph indexed by ``index_set``
            on the subset ``X`` of ``self``.

            Let `b \in B` be an element of weight `0`, so `\varepsilon_j(b)
            = \varphi_j(b)` for all `j \in I`, where `I` is the indexing
            set. We say `b'` is an `i`-elementary dual equivalence
            transformation of `b` (where `i \in I`) if

            * `\varepsilon_i(b) = 1` and `\varepsilon_{i-1}(b) = 0`, and
            * `b' = f_{i-1} f_i e_{i-1} e_i b`.

            We can do the inverse procedure by interchanging `i` and `i-1`
            above.

            .. NOTE::

                If the index set is not an ordered interval, we let
                `i - 1` mean the index appearing before `i` in `I`.

            This definition comes from [As2008]_ Section 4 (where our
            `\varphi_j(b)` and `\varepsilon_j(b)` are denoted by
            `\epsilon(b, j)` and `-\delta(b, j)`, respectively).

            The dual equivalence graph of `B` is defined to be the
            colored graph whose vertices are the elements of `B` of
            weight `0`, and whose edges of color `i` (for `i \in I`)
            connect pairs `\{ b, b' \}` such that `b'` is an
            `i`-elementary dual equivalence transformation of `b`.

            .. NOTE::

                This dual equivalence graph is a generalization of
                `\mathcal{G}\left(\mathcal{X}\right)` in [As2008]_
                Section 4 except we do not require
                `\varepsilon_i(b) = 0, 1` for all `i`.

            This definition can be generalized by choosing a subset `X`
            of the set of all vertices of `B` of weight `0`, and
            restricting the dual equivalence graph to the vertex set
            `X`.

            INPUT:

            - ``X`` -- (optional) the vertex set `X` (default:
              the whole set of vertices of ``self`` of weight `0`)
            - ``index_set`` -- (optional) the index set `I`
              (default: the whole index set of ``self``); this has
              to be a subset of the index set of ``self`` (as a list
              or tuple)
            - ``directed`` -- (default: ``True``) whether to have the
              dual equivalence graph be directed, where the head of
              an edge `b - b'` is `b` and the tail is
              `b' = f_{i-1} f_i e_{i-1} e_i b`)

            .. SEEALSO::

                :meth:`sage.combinat.partition.Partition.dual_equivalence_graph`

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',3], shape=[2,2])
                sage: G = T.dual_equivalence_graph()
                sage: sorted(G.edges())
                [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
                 ([[1, 2], [3, 4]], [[1, 3], [2, 4]], 3)]
                sage: T = crystals.Tableaux(['A',4], shape=[3,2])
                sage: G = T.dual_equivalence_graph()
                sage: sorted(G.edges())
                [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
                 ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
                 ([[1, 2, 5], [3, 4]], [[1, 3, 5], [2, 4]], 3),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
                 ([[1, 2, 3], [4, 5]], [[1, 2, 4], [3, 5]], 4)]

                sage: T = crystals.Tableaux(['A',4], shape=[3,1])
                sage: G = T.dual_equivalence_graph(index_set=[1,2,3])
                sage: G.vertices()
                [[[1, 3, 4], [2]], [[1, 2, 4], [3]], [[1, 2, 3], [4]]]
                sage: G.edges()
                [([[1, 3, 4], [2]], [[1, 2, 4], [3]], 2),
                 ([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3)]

            TESTS::

                sage: T = crystals.Tableaux(['A',4], shape=[3,1])
                sage: G = T.dual_equivalence_graph(index_set=[2,3])
                sage: sorted(G.edges())
                [([[1, 2, 4], [3]], [[1, 2, 3], [4]], 3),
                 ([[2, 4, 5], [3]], [[2, 3, 5], [4]], 3)]
                sage: sorted(G.vertices())
                [[[1, 3, 4], [2]],
                 [[1, 2, 4], [3]],
                 [[2, 4, 5], [3]],
                 [[1, 2, 3], [4]],
                 [[2, 3, 5], [4]],
                 [[1, 1, 1], [5]],
                 [[1, 1, 5], [5]],
                 [[1, 5, 5], [5]],
                 [[2, 3, 4], [5]]]
            """
            if index_set is None:
                index_set = self.index_set()

            def wt_zero(x):
                for i in index_set:
                    if x.epsilon(i) != x.phi(i):
                        return False
                return True

            if X is None:
                X = [x for x in self if wt_zero(x)]
                checker = lambda x: True
            elif any(not wt_zero(x) for x in X):
                raise ValueError("the elements are not all weight 0")
            else:
                checker = lambda x: x in X

            edges = []
            for x in X:
                for k, i in enumerate(index_set[1:]):
                    im = index_set[k]
                    if x.epsilon(i) == 1 and x.epsilon(im) == 0:
                        y = x.e(i).e(im).f(i).f(im)
                        if checker(y):
                            edges.append([x, y, i])
            from sage.graphs.all import DiGraph
            G = DiGraph([X, edges],
                        format="vertices_and_edges",
                        immutable=True)
            if have_dot2tex():
                G.set_latex_options(
                    format="dot2tex",
                    edge_labels=True,
                    color_by_label=self.cartan_type()._index_set_coloring)
            return G
Example #20
0
        def dual_equivalence_class(self, index_set=None):
            r"""
            Return the dual equivalence class indexed by ``index_set``
            of ``self``.

            The dual equivalence class of an element `b \in B`
            is the set of all elements of `B` reachable from
            `b` via sequences of `i`-elementary dual equivalence
            relations (i.e., `i`-elementary dual equivalence
            transformations and their inverses) for `i` in the index
            set of `B`.

            For this to be well-defined, the element `b` has to be
            of weight `0` with respect to `I`; that is, we need to have
            `\varepsilon_j(b) = \varphi_j(b)` for all `j \in I`.

            See [As2008]_. See also :meth:`dual_equivalence_graph` for
            a definition of `i`-elementary dual equivalence
            transformations.

            INPUT:

            - ``index_set`` -- (optional) the index set `I`
              (default: the whole index set of the crystal); this has
              to be a subset of the index set of the crystal (as a list
              or tuple)

            OUTPUT:

            The dual equivalence class of ``self`` indexed by the
            subset ``index_set``. This class is returned as an
            undirected edge-colored multigraph. The color of an edge
            is the index `i` of the dual equivalence relation it
            encodes.

            .. SEEALSO::

                - :meth:`~sage.categories.regular_crystals.RegularCrystals.ParentMethods.dual_equivalence_graph`
                - :meth:`sage.combinat.partition.Partition.dual_equivalence_graph`

            EXAMPLES::

                sage: T = crystals.Tableaux(['A',3], shape=[2,2])
                sage: G = T(2,1,4,3).dual_equivalence_class()
                sage: sorted(G.edges())
                [([[1, 3], [2, 4]], [[1, 2], [3, 4]], 2),
                 ([[1, 3], [2, 4]], [[1, 2], [3, 4]], 3)]
                sage: T = crystals.Tableaux(['A',4], shape=[3,2])
                sage: G = T(2,1,4,3,5).dual_equivalence_class()
                sage: sorted(G.edges())
                [([[1, 3, 5], [2, 4]], [[1, 3, 4], [2, 5]], 4),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 2),
                 ([[1, 3, 5], [2, 4]], [[1, 2, 5], [3, 4]], 3),
                 ([[1, 3, 4], [2, 5]], [[1, 2, 4], [3, 5]], 2),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 3),
                 ([[1, 2, 4], [3, 5]], [[1, 2, 3], [4, 5]], 4)]
            """
            if index_set is None:
                index_set = self.index_set()

            for i in index_set:
                if self.epsilon(i) != self.phi(i):
                    raise ValueError("the element is not weight 0")

            visited = set([])
            todo = set([self])
            edges = []
            while todo:
                x = todo.pop()
                visited.add(x)
                for k, i in enumerate(index_set[1:]):
                    im = index_set[k]
                    if x.epsilon(i) == 1 and x.epsilon(im) == 0:
                        y = x.e(i).e(im).f(i).f(im)
                        if [y, x, i] not in edges:
                            edges.append([x, y, i])
                        if y not in visited:
                            todo.add(y)
                    if x.epsilon(i) == 0 and x.epsilon(im) == 1:
                        y = x.e(im).e(i).f(im).f(i)
                        if [y, x, i] not in edges:
                            edges.append([x, y, i])
                        if y not in visited:
                            todo.add(y)
            from sage.graphs.graph import Graph
            G = Graph([visited, edges],
                      format="vertices_and_edges",
                      immutable=True,
                      multiedges=True)
            if have_dot2tex():
                G.set_latex_options(
                    format="dot2tex",
                    edge_labels=True,
                    color_by_label=self.cartan_type()._index_set_coloring)
            return G
Example #21
0
    def markov_chain_digraph(self, action = 'promotion', labeling = 'identity'):
        r"""
        Returns the digraph of the action of generalized promotion or tau on ``self``

        INPUT:

        - ``action`` -- 'promotion' or 'tau' (default: 'promotion')
        - ``labeling`` -- 'identity' or 'source' (default: 'identity')

        .. todo::

            - generalize this feature by accepting a family of operators as input
            - move up in some appropriate category

        This method creates a graph with vertices being the linear extensions of a given finite
        poset and an edge from `\pi` to `\pi'` if `\pi' = \pi \partial_i` where `\partial_i` is
        the promotion operator (see :meth:`promotion`) if ``action`` is set to ``promotion``
        and `\tau_i` (see :meth:`tau`) if ``action`` is set to ``tau``. The label of the edge
        is `i` (resp. `\pi_i`) if ``labeling`` is set to ``identity`` (resp. ``source``).

        EXAMPLES::

            sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension = True)
            sage: L = P.linear_extensions()
            sage: G = L.markov_chain_digraph(); G
            Looped multi-digraph on 5 vertices
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
            ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 2, 4, 3], 4),
            ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
            ([1, 4, 2, 3], [1, 2, 3, 4], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3), ([1, 4, 2, 3], [1, 4, 2, 3], 4),
            ([2, 1, 3, 4], [1, 2, 4, 3], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 2),
            ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 2),
            ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 4)]

            sage: G = L.markov_chain_digraph(labeling = 'source')
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
            ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 4), ([1, 2, 4, 3], [1, 2, 4, 3], 3),
            ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
            ([1, 4, 2, 3], [1, 2, 3, 4], 4), ([1, 4, 2, 3], [1, 4, 2, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
            ([2, 1, 3, 4], [1, 2, 4, 3], 2), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 1),
            ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 2), ([2, 1, 4, 3], [2, 1, 3, 4], 1),
            ([2, 1, 4, 3], [2, 1, 3, 4], 4), ([2, 1, 4, 3], [2, 1, 4, 3], 3)]

        The edges of the graph are by default colored using blue for
        edge 1, red for edge 2, green for edge 3, and yellow for edge 4::

            sage: view(G) #optional - dot2tex graphviz

        Alternatively, one may get the graph of the action of the ``tau`` operator::

            sage: G = L.markov_chain_digraph(action='tau'); G
            Looped multi-digraph on 5 vertices
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3), ([1, 2, 3, 4], [2, 1, 3, 4], 1),
            ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 4, 3], 1),
            ([1, 4, 2, 3], [1, 2, 4, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 1), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
            ([2, 1, 3, 4], [1, 2, 3, 4], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 2), ([2, 1, 3, 4], [2, 1, 4, 3], 3),
            ([2, 1, 4, 3], [1, 2, 4, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 2)]
            sage: view(G) #optional - dot2tex graphviz

        .. seealso:: :meth:`markov_chain_transition_matrix`, :meth:`promotion`, :meth:`tau`

        TESTS::

            sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension = True, facade = True)
            sage: L = P.linear_extensions()
            sage: G = L.markov_chain_digraph(labeling = 'source'); G
            Looped multi-digraph on 5 vertices
        """
        d = dict([x,dict([y,[]] for y in self)] for x in self)
        if action == 'promotion':
            R = range(self.poset().cardinality())
        else:
            R = range(self.poset().cardinality()-1)
        if labeling == 'source':
            for x in self:
                for i in R:
                    child = getattr(x, action)(i+1)
                    d[x][child]+=[self.poset().unwrap(x[i])]
        else:
            for x in self:
                for i in R:
                    child = getattr(x, action)(i+1)
                    d[x][child]+=[i+1]
        G = DiGraph(d)
        if have_dot2tex():
            G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = {1:"blue", 2:"red", 3:"green", 4:"yellow"})
            #G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = {1:"green", 2:"blue", 3:"brown", 4:"red"})
        return G
Example #22
0
    def markov_chain_digraph(self, action='promotion', labeling='identity'):
        r"""
        Returns the digraph of the action of generalized promotion or tau on ``self``

        INPUT:

        - ``action`` -- 'promotion' or 'tau' (default: 'promotion')
        - ``labeling`` -- 'identity' or 'source' (default: 'identity')

        .. todo::

            - generalize this feature by accepting a family of operators as input
            - move up in some appropriate category

        This method creates a graph with vertices being the linear extensions of a given finite
        poset and an edge from `\pi` to `\pi'` if `\pi' = \pi \partial_i` where `\partial_i` is
        the promotion operator (see :meth:`promotion`) if ``action`` is set to ``promotion``
        and `\tau_i` (see :meth:`tau`) if ``action`` is set to ``tau``. The label of the edge
        is `i` (resp. `\pi_i`) if ``labeling`` is set to ``identity`` (resp. ``source``).

        EXAMPLES::

            sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension = True)
            sage: L = P.linear_extensions()
            sage: G = L.markov_chain_digraph(); G
            Looped multi-digraph on 5 vertices
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
            ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 2, 4, 3], 4),
            ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
            ([1, 4, 2, 3], [1, 2, 3, 4], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3), ([1, 4, 2, 3], [1, 4, 2, 3], 4),
            ([2, 1, 3, 4], [1, 2, 4, 3], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 2),
            ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 2),
            ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 4)]

            sage: G = L.markov_chain_digraph(labeling = 'source')
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 4), ([1, 2, 3, 4], [1, 2, 4, 3], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3),
            ([1, 2, 3, 4], [2, 1, 4, 3], 1), ([1, 2, 4, 3], [1, 2, 3, 4], 4), ([1, 2, 4, 3], [1, 2, 4, 3], 3),
            ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 3, 4], 1), ([1, 4, 2, 3], [1, 2, 3, 4], 1),
            ([1, 4, 2, 3], [1, 2, 3, 4], 4), ([1, 4, 2, 3], [1, 4, 2, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
            ([2, 1, 3, 4], [1, 2, 4, 3], 2), ([2, 1, 3, 4], [2, 1, 3, 4], 4), ([2, 1, 3, 4], [2, 1, 4, 3], 1),
            ([2, 1, 3, 4], [2, 1, 4, 3], 3), ([2, 1, 4, 3], [1, 4, 2, 3], 2), ([2, 1, 4, 3], [2, 1, 3, 4], 1),
            ([2, 1, 4, 3], [2, 1, 3, 4], 4), ([2, 1, 4, 3], [2, 1, 4, 3], 3)]

        The edges of the graph are by default colored using blue for
        edge 1, red for edge 2, green for edge 3, and yellow for edge 4::

            sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)

        Alternatively, one may get the graph of the action of the ``tau`` operator::

            sage: G = L.markov_chain_digraph(action='tau'); G
            Looped multi-digraph on 5 vertices
            sage: sorted(G.vertices(), key = repr)
            [[1, 2, 3, 4], [1, 2, 4, 3], [1, 4, 2, 3], [2, 1, 3, 4], [2, 1, 4, 3]]
            sage: sorted(G.edges(), key = repr)
            [([1, 2, 3, 4], [1, 2, 3, 4], 2), ([1, 2, 3, 4], [1, 2, 4, 3], 3), ([1, 2, 3, 4], [2, 1, 3, 4], 1),
            ([1, 2, 4, 3], [1, 2, 3, 4], 3), ([1, 2, 4, 3], [1, 4, 2, 3], 2), ([1, 2, 4, 3], [2, 1, 4, 3], 1),
            ([1, 4, 2, 3], [1, 2, 4, 3], 2), ([1, 4, 2, 3], [1, 4, 2, 3], 1), ([1, 4, 2, 3], [1, 4, 2, 3], 3),
            ([2, 1, 3, 4], [1, 2, 3, 4], 1), ([2, 1, 3, 4], [2, 1, 3, 4], 2), ([2, 1, 3, 4], [2, 1, 4, 3], 3),
            ([2, 1, 4, 3], [1, 2, 4, 3], 1), ([2, 1, 4, 3], [2, 1, 3, 4], 3), ([2, 1, 4, 3], [2, 1, 4, 3], 2)]
            sage: view(G) # optional - dot2tex graphviz, not tested (opens external window)

        .. SEEALSO:: :meth:`markov_chain_transition_matrix`, :meth:`promotion`, :meth:`tau`

        TESTS::

            sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension = True, facade = True)
            sage: L = P.linear_extensions()
            sage: G = L.markov_chain_digraph(labeling = 'source'); G
            Looped multi-digraph on 5 vertices
        """
        d = dict([x, dict([y, []] for y in self)] for x in self)
        if action == 'promotion':
            R = list(range(self.poset().cardinality()))
        else:
            R = list(range(self.poset().cardinality() - 1))
        if labeling == 'source':
            for x in self:
                for i in R:
                    child = getattr(x, action)(i + 1)
                    d[x][child] += [self.poset().unwrap(x[i])]
        else:
            for x in self:
                for i in R:
                    child = getattr(x, action)(i + 1)
                    d[x][child] += [i + 1]
        G = DiGraph(d, format="dict_of_dicts")
        if have_dot2tex():
            G.set_latex_options(format="dot2tex",
                                edge_labels=True,
                                color_by_label={
                                    1: "blue",
                                    2: "red",
                                    3: "green",
                                    4: "yellow"
                                })
            #G.set_latex_options(format="dot2tex", edge_labels = True, color_by_label = {1:"green", 2:"blue", 3:"brown", 4:"red"})
        return G
Example #23
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux for type `B_n^{(1)}`.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['B', 3, 1], [[2, 1]])
            sage: from sage.combinat.rigged_configurations.bij_type_B import RCToKRTBijectionTypeB
            sage: RCToKRTBijectionTypeB(RC(partition_list=[[1],[1,1],[1]])).run()
            [[3], [0]]

            sage: RC = RiggedConfigurations(['B', 3, 1], [[3, 1]])
            sage: x = RC(partition_list=[[],[1],[1]])
            sage: RCToKRTBijectionTypeB(x).run()
            [[1], [3], [-2]]
            sage: bij = RCToKRTBijectionTypeB(x)
            sage: bij.run(build_graph=True)
            [[1], [3], [-2]]
            sage: bij._graph
            Digraph on 6 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Check to see if we are a spinor
            if dim[0] == self.n:
                # Perform the spinor bijection by converting to type A_{2n-1}^{(2)}
                #   doing the bijection there and pulling back

                from sage.combinat.rigged_configurations.bij_type_A2_odd import RCToKRTBijectionTypeA2Odd
                from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations
                from sage.combinat.rigged_configurations.rigged_partition import RiggedPartition, RiggedPartitionTypeB
        
                # Convert to a type A_{2n-1}^{(2)} RC
                RC = RiggedConfigurations(['A', 2*self.n-1, 2], self.cur_dims)
                if verbose:
                    print("====================")
                    print(repr(RC(*self.cur_partitions, use_vacancy_numbers=True)))
                    print("--------------------")
                    print(ret_crystal_path)
                    print("--------------------\n")
                    print("Applying doubling map\n")
                # Convert the n-th partition into a regular rigged partition
                self.cur_partitions[-1] = RiggedPartition(self.cur_partitions[-1]._list,
                                                          self.cur_partitions[-1].rigging,
                                                          self.cur_partitions[-1].vacancy_numbers)

                bij = RCToKRTBijectionTypeA2Odd(RC(*self.cur_partitions, use_vacancy_numbers=True))
                for i in range(len(self.cur_dims)):
                    if bij.cur_dims[i][0] != self.n:
                        bij.cur_dims[i][1] *= 2
                for i in range(self.n-1):
                    for j in range(len(bij.cur_partitions[i])):
                        bij.cur_partitions[i]._list[j] *= 2
                        bij.cur_partitions[i].rigging[j] *= 2
                        bij.cur_partitions[i].vacancy_numbers[j] *= 2

                if build_graph:
                    y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                    self._graph.append([self._graph[-1][1], (y, len(self._graph)), '2x'])

                # Perform the type A_{2n-1}^{(2)} bijection

                # Iterate over each column
                for dummy_var in range(dim[1]):
                    # Split off a new column if necessary
                    if bij.cur_dims[0][1] > 1:
                        bij.cur_dims[0][1] -= 1
                        bij.cur_dims.insert(0, [dim[0], 1])

                        # Perform the corresponding splitting map on rigged configurations
                        # All it does is update the vacancy numbers on the RC side
                        for a in range(self.n):
                            bij._update_vacancy_numbers(a)

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), 'ls'])

                    while bij.cur_dims[0][0]: # > 0:
                        if verbose:
                            print("====================")
                            print(repr(RC(*bij.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")

                        ht = bij.cur_dims[0][0]
                        bij.cur_dims[0][0] = bij._next_index(ht)
                        b = bij.next_state(ht)
                        # Make sure we have a crystal letter
                        ret_crystal_path[-1].append(letters(b)) # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                    bij.cur_dims.pop(0) # Pop off the leading column

                self.cur_dims.pop(0) # Pop off the spin rectangle

                self.cur_partitions = bij.cur_partitions
                # Convert the n-th partition back into the special type B one
                self.cur_partitions[-1] = RiggedPartitionTypeB(self.cur_partitions[-1])

                # Convert back to a type B_n^{(1)}
                if verbose:
                    print("====================")
                    print(repr(self.rigged_con.parent()(*bij.cur_partitions, use_vacancy_numbers=True)))
                    print("--------------------")
                    print(ret_crystal_path)
                    print("--------------------\n")
                    print("Applying halving map\n")

                for i in range(self.n-1):
                    for j in range(len(self.cur_partitions[i])):
                        self.cur_partitions[i]._list[j] //= 2
                        self.cur_partitions[i].rigging[j] //= 2
                        self.cur_partitions[i].vacancy_numbers[j] //= 2

                if build_graph:
                    y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                    self._graph.append([self._graph[-1][1], (y, len(self._graph)), '1/2x'])
            else:
                # Perform the regular type B_n^{(1)} bijection

                # Iterate over each column
                for dummy_var in range(dim[1]):
                    # Split off a new column if necessary
                    if self.cur_dims[0][1] > 1:
                        if verbose:
                            print("====================")
                            print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")
                            print("Applying column split")

                        self.cur_dims[0][1] -= 1
                        self.cur_dims.insert(0, [dim[0], 1])

                        # Perform the corresponding splitting map on rigged configurations
                        # All it does is update the vacancy numbers on the RC side
                        for a in range(self.n):
                            self._update_vacancy_numbers(a)

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), '2x'])

                    while self.cur_dims[0][0]: #> 0:
                        if verbose:
                            print("====================")
                            print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")

                        self.cur_dims[0][0] -= 1 # This takes care of the indexing
                        b = self.next_state(self.cur_dims[0][0])

                        # Make sure we have a crystal letter
                        ret_crystal_path[-1].append(letters(b)) # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                    self.cur_dims.pop(0) # Pop off the leading column

        if build_graph:
            self._graph.pop(0) # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph)
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex", edge_labels=True)

        return self.KRT(pathlist=ret_crystal_path)
Example #24
0
        def digraph(self, subset=None, index_set=None):
            """
            Returns 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

            EXAMPLES::

                sage: C = Crystals().example(5)
                sage: C.digraph()
                Digraph on 6 vertices

            The edges of the crystal graph are by default colored using blue for edge 1, red for edge 2,
            and green for edge 3::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            One may also overwrite the colors::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Or one may add colors to yet unspecified edges::

                sage: C = Crystals().example(4)
                sage: G = C.digraph()
                sage: C.cartan_type()._index_set_coloring[4]="purple"
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Here is an example of how to take the top part up to a given depth of an infinite dimensional
            crystal::

                sage: C = CartanType(['C',2,1])
                sage: La = C.root_system().weight_lattice().fundamental_weights()
                sage: T = HighestWeightCrystal(La[0])
                sage: S = T.subcrystal(max_depth=3)
                sage: G = T.digraph(subset=S); G
                Digraph on 5 vertices
                sage: G.vertices()
                [(1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
                (-Lambda[0] + 2*Lambda[1] - delta,), (Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
                (1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta), (Lambda[0],)]

            Here is a way to construct a picture of a Demazure crystal using
            the ``subset`` option::

                sage: B = CrystalOfTableaux(['A',2], shape=[2,1])
                sage: C = CombinatorialFreeModule(QQ,B)
                sage: t = B.highest_weight_vector()
                sage: b = C(t)
                sage: D = B.demazure_operator(b,[2,1]); D
                B[[[1, 1], [2]]] + B[[[1, 2], [2]]] + B[[[1, 3], [2]]] + B[[[1, 1], [3]]] + B[[[1, 3], [3]]]
                sage: G = B.digraph(subset=D.support())
                sage: G.vertices()
                [[[1, 1], [2]], [[1, 2], [2]], [[1, 3], [2]], [[1, 1], [3]], [[1, 3], [3]]]
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            We can also choose to display particular arrows using the
            ``index_set`` option::

                sage: C = KirillovReshetikhinCrystal(['D',4,1], 2, 1)
                sage: G = C.digraph(index_set=[1,3])
                sage: len(G.edges())
                20
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            TODO: add more tests
            """
            from sage.graphs.all import DiGraph
            from sage.categories.highest_weight_crystals import HighestWeightCrystals
            d = {}
            if self in HighestWeightCrystals:
                f = lambda (u,v,label): ({})
            else:
                f = lambda (u,v,label): ({"backward":label ==0})

            # Parse optional arguments
            if subset is None:
                subset = self
            if index_set is None:
                index_set = self.index_set()

            for x in subset:
                d[x] = {}
                for i in index_set:
                    child = x.f(i)
                    if child is None or child not in subset:
                        continue
                    d[x][child]=i
            G = DiGraph(d)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex",
                                    edge_labels = True,
                                    color_by_label = self.cartan_type()._index_set_coloring,
                                    edge_options = f)
            return G
Example #25
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux for type `B_n^{(1)}`.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['B', 3, 1], [[2, 1]])
            sage: from sage.combinat.rigged_configurations.bij_type_B import RCToKRTBijectionTypeB
            sage: RCToKRTBijectionTypeB(RC(partition_list=[[1],[1,1],[1]])).run()
            [[3], [0]]

            sage: RC = RiggedConfigurations(['B', 3, 1], [[3, 1]])
            sage: x = RC(partition_list=[[],[1],[1]])
            sage: RCToKRTBijectionTypeB(x).run()
            [[1], [3], [-2]]
            sage: bij = RCToKRTBijectionTypeB(x)
            sage: bij.run(build_graph=True)
            [[1], [3], [-2]]
            sage: bij._graph
            Digraph on 6 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Check to see if we are a spinor
            if dim[0] == self.n:
                # Perform the spinor bijection by converting to type A_{2n-1}^{(2)}
                #   doing the bijection there and pulling back

                from sage.combinat.rigged_configurations.bij_type_A2_odd import RCToKRTBijectionTypeA2Odd
                from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations
                from sage.combinat.rigged_configurations.rigged_partition import RiggedPartition, RiggedPartitionTypeB
        
                # Convert to a type A_{2n-1}^{(2)} RC
                RC = RiggedConfigurations(['A', 2*self.n-1, 2], self.cur_dims)
                if verbose:
                    print("====================")
                    print(repr(RC(*self.cur_partitions, use_vacancy_numbers=True)))
                    print("--------------------")
                    print(ret_crystal_path)
                    print("--------------------\n")
                    print("Applying doubling map\n")
                # Convert the n-th partition into a regular rigged partition
                self.cur_partitions[-1] = RiggedPartition(self.cur_partitions[-1]._list,
                                                          self.cur_partitions[-1].rigging,
                                                          self.cur_partitions[-1].vacancy_numbers)

                bij = RCToKRTBijectionTypeA2Odd(RC(*self.cur_partitions, use_vacancy_numbers=True))
                for i in range(len(self.cur_dims)):
                    if bij.cur_dims[i][0] != self.n:
                        bij.cur_dims[i][1] *= 2
                for i in range(self.n-1):
                    for j in range(len(bij.cur_partitions[i])):
                        bij.cur_partitions[i]._list[j] *= 2
                        bij.cur_partitions[i].rigging[j] *= 2
                        bij.cur_partitions[i].vacancy_numbers[j] *= 2

                if build_graph:
                    y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                    self._graph.append([self._graph[-1][1], (y, len(self._graph)), '2x'])

                # Perform the type A_{2n-1}^{(2)} bijection

                # Iterate over each column
                for dummy_var in range(dim[1]):
                    # Split off a new column if necessary
                    if bij.cur_dims[0][1] > 1:
                        bij.cur_dims[0][1] -= 1
                        bij.cur_dims.insert(0, [dim[0], 1])

                        # Perform the corresponding splitting map on rigged configurations
                        # All it does is update the vacancy numbers on the RC side
                        for a in range(self.n):
                            bij._update_vacancy_numbers(a)

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), 'ls'])

                    while bij.cur_dims[0][0]: # > 0:
                        if verbose:
                            print("====================")
                            print(repr(RC(*bij.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")

                        ht = bij.cur_dims[0][0]
                        bij.cur_dims[0][0] = bij._next_index(ht)
                        b = bij.next_state(ht)
                        # Make sure we have a crystal letter
                        ret_crystal_path[-1].append(letters(b)) # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                    bij.cur_dims.pop(0) # Pop off the leading column

                self.cur_dims.pop(0) # Pop off the spin rectangle

                self.cur_partitions = bij.cur_partitions
                # Convert the n-th partition back into the special type B one
                self.cur_partitions[-1] = RiggedPartitionTypeB(self.cur_partitions[-1])

                # Convert back to a type B_n^{(1)}
                if verbose:
                    print("====================")
                    print(repr(self.rigged_con.parent()(*bij.cur_partitions, use_vacancy_numbers=True)))
                    print("--------------------")
                    print(ret_crystal_path)
                    print("--------------------\n")
                    print("Applying halving map\n")

                for i in range(self.n-1):
                    for j in range(len(self.cur_partitions[i])):
                        self.cur_partitions[i]._list[j] //= 2
                        self.cur_partitions[i].rigging[j] //= 2
                        self.cur_partitions[i].vacancy_numbers[j] //= 2

                if build_graph:
                    y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                    self._graph.append([self._graph[-1][1], (y, len(self._graph)), '1/2x'])
            else:
                # Perform the regular type B_n^{(1)} bijection

                # Iterate over each column
                for dummy_var in range(dim[1]):
                    # Split off a new column if necessary
                    if self.cur_dims[0][1] > 1:
                        if verbose:
                            print("====================")
                            print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")
                            print("Applying column split")

                        self.cur_dims[0][1] -= 1
                        self.cur_dims.insert(0, [dim[0], 1])

                        # Perform the corresponding splitting map on rigged configurations
                        # All it does is update the vacancy numbers on the RC side
                        for a in range(self.n):
                            self._update_vacancy_numbers(a)

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), '2x'])

                    while self.cur_dims[0][0]: #> 0:
                        if verbose:
                            print("====================")
                            print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")

                        self.cur_dims[0][0] -= 1 # This takes care of the indexing
                        b = self.next_state(self.cur_dims[0][0])

                        # Make sure we have a crystal letter
                        ret_crystal_path[-1].append(letters(b)) # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                    self.cur_dims.pop(0) # Pop off the leading column

        if build_graph:
            self._graph.pop(0) # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph)
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex", edge_labels=True)

        return self.KRT(pathlist=ret_crystal_path)
Example #26
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 1]])
            sage: x = RC(partition_list=[[1],[1],[1],[1]])
            sage: from sage.combinat.rigged_configurations.bij_type_A import RCToKRTBijectionTypeA
            sage: RCToKRTBijectionTypeA(x).run()
            [[2], [5]]
            sage: bij = RCToKRTBijectionTypeA(x)
            sage: bij.run(build_graph=True)
            [[2], [5]]
            sage: bij._graph
            Digraph on 3 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Iterate over each column
            for dummy_var in range(dim[1]):
                # Split off a new column if necessary
                if self.cur_dims[0][1] > 1:
                    if verbose:
                        print("====================")
                        print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying column split")

                    self.cur_dims[0][1] -= 1
                    self.cur_dims.insert(0, [dim[0], 1])

                    # Perform the corresponding splitting map on rigged configurations
                    # All it does is update the vacancy numbers on the RC side
                    for a in range(self.n):
                        self._update_vacancy_numbers(a)

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), 'ls'])

                while self.cur_dims[0][0] > 0:
                    if verbose:
                        print("====================")
                        print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")

                    self.cur_dims[0][0] -= 1 # This takes care of the indexing
                    b = self.next_state(self.cur_dims[0][0])

                    # Make sure we have a crystal letter
                    ret_crystal_path[-1].append(letters(b)) # Append the rank

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                self.cur_dims.pop(0) # Pop off the leading column

        if build_graph:
            self._graph.pop(0) # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph)
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex", edge_labels=True)

        # Basic check to make sure we end with the empty configuration
        #tot_len = sum([len(rp) for rp in self.cur_partitions])
        #if tot_len != 0:
        #    print "Invalid bijection end for:"
        #    print self.rigged_con
        #    print "-----------------------"
        #    print self.cur_partitions
        #    raise ValueError("Invalid bijection end")
        return self.KRT(pathlist=ret_crystal_path)
Example #27
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux for type `D_n^{(1)}`.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['D', 4, 1], [[2, 1]])
            sage: x = RC(partition_list=[[1],[1],[1],[1]])
            sage: from sage.combinat.rigged_configurations.bij_type_D import RCToKRTBijectionTypeD
            sage: RCToKRTBijectionTypeD(x).run()
            [[2], [-3]]
            sage: bij = RCToKRTBijectionTypeD(x)
            sage: bij.run(build_graph=True)
            [[2], [-3]]
            sage: bij._graph
            Digraph on 3 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Iterate over each column
            for dummy_var in range(dim[1]):
                # Split off a new column if necessary
                if self.cur_dims[0][1] > 1:
                    self.cur_dims[0][1] -= 1
                    self.cur_dims.insert(0, [dim[0], 1])

                    # Perform the corresponding splitting map on rigged configurations
                    # All it does is update the vacancy numbers on the RC side
                    for a in range(self.n):
                        self._update_vacancy_numbers(a)

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), 'ls'])

                # Check to see if we are a spinor
                if dim[0] >= self.n - 1:
                    if verbose:
                        print("====================")
                        print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying doubling map")
                    self.doubling_map()

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), '2x'])

                    if dim[0] == self.n - 1:
                        if verbose:
                            print("====================")
                            print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")
                        b = self.next_state(self.n)
                        if b == self.n:
                            b = -self.n
                        ret_crystal_path[-1].append(letters(b)) # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                            self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                while self.cur_dims[0][0] > 0:
                    if verbose:
                        print("====================")
                        print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")

                    self.cur_dims[0][0] -= 1 # This takes care of the indexing
                    b = self.next_state(self.cur_dims[0][0])
                    
                    # Corrections for spinor
                    if dim[0] == self.n and b == -self.n \
                      and self.cur_dims[0][0] == self.n - 1:
                        b = -(self.n-1)

                    # Make sure we have a crystal letter
                    ret_crystal_path[-1].append(letters(b)) # Append the rank

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), letters(b)])

                self.cur_dims.pop(0) # Pop off the leading column

                # Check to see if we were a spinor
                if dim[0] >= self.n-1:
                    if verbose:
                        print("====================")
                        print(repr(self.rigged_con.parent()(*self.cur_partitions, use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying halving map")
                    self.halving_map()

                    if build_graph:
                        y = self.rigged_con.parent()(*[x._clone() for x in self.cur_partitions], use_vacancy_numbers=True)
                        self._graph.append([self._graph[-1][1], (y, len(self._graph)), '1/2x'])

        if build_graph:
            self._graph.pop(0) # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph, format="list_of_edges")
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex", edge_labels=True)

        return self.KRT(pathlist=ret_crystal_path)
Example #28
0
    def run(self, verbose=False, build_graph=False):
        """
        Run the bijection from rigged configurations to tensor product of KR
        tableaux for type `D_n^{(1)}`.

        INPUT:

        - ``verbose`` -- (default: ``False``) display each step in the
          bijection
        - ``build_graph`` -- (default: ``False``) build the graph of each
          step of the bijection

        EXAMPLES::

            sage: RC = RiggedConfigurations(['D', 4, 1], [[2, 1]])
            sage: x = RC(partition_list=[[1],[1],[1],[1]])
            sage: from sage.combinat.rigged_configurations.bij_type_D import RCToKRTBijectionTypeD
            sage: RCToKRTBijectionTypeD(x).run()
            [[2], [-3]]
            sage: bij = RCToKRTBijectionTypeD(x)
            sage: bij.run(build_graph=True)
            [[2], [-3]]
            sage: bij._graph
            Digraph on 3 vertices
        """
        from sage.combinat.crystals.letters import CrystalOfLetters
        letters = CrystalOfLetters(
            self.rigged_con.parent()._cartan_type.classical())

        # This is technically bad, but because the first thing we do is append
        #   an empty list to ret_crystal_path, we correct this. We do it this
        #   way so that we do not have to remove an empty list after the
        #   bijection has been performed.
        ret_crystal_path = []

        for dim in self.rigged_con.parent().dims:
            ret_crystal_path.append([])

            # Iterate over each column
            for dummy_var in range(dim[1]):
                # Split off a new column if necessary
                if self.cur_dims[0][1] > 1:
                    self.cur_dims[0][1] -= 1
                    self.cur_dims.insert(0, [dim[0], 1])

                    # Perform the corresponding splitting map on rigged configurations
                    # All it does is update the vacancy numbers on the RC side
                    for a in range(self.n):
                        self._update_vacancy_numbers(a)

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append(
                            [self._graph[-1][1], (y, len(self._graph)), 'ls'])

                # Check to see if we are a spinor
                if dim[0] >= self.n - 1:
                    if verbose:
                        print("====================")
                        print(
                            repr(self.rigged_con.parent()(
                                *self.cur_partitions,
                                use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying doubling map")
                    self.doubling_map()

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append(
                            [self._graph[-1][1], (y, len(self._graph)), '2x'])

                    if dim[0] == self.n - 1:
                        if verbose:
                            print("====================")
                            print(
                                repr(self.rigged_con.parent()(
                                    *self.cur_partitions,
                                    use_vacancy_numbers=True)))
                            print("--------------------")
                            print(ret_crystal_path)
                            print("--------------------\n")
                        b = self.next_state(self.n)
                        if b == self.n:
                            b = -self.n
                        ret_crystal_path[-1].append(
                            letters(b))  # Append the rank

                        if build_graph:
                            y = self.rigged_con.parent()(
                                *[x._clone() for x in self.cur_partitions],
                                use_vacancy_numbers=True)
                            self._graph.append([
                                self._graph[-1][1], (y, len(self._graph)),
                                letters(b)
                            ])

                while self.cur_dims[0][0] > 0:
                    if verbose:
                        print("====================")
                        print(
                            repr(self.rigged_con.parent()(
                                *self.cur_partitions,
                                use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")

                    self.cur_dims[0][0] -= 1  # This takes care of the indexing
                    b = self.next_state(self.cur_dims[0][0])

                    # Corrections for spinor
                    if dim[0] == self.n and b == -self.n \
                      and self.cur_dims[0][0] == self.n - 1:
                        b = -(self.n - 1)

                    # Make sure we have a crystal letter
                    ret_crystal_path[-1].append(letters(b))  # Append the rank

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append([
                            self._graph[-1][1], (y, len(self._graph)),
                            letters(b)
                        ])

                self.cur_dims.pop(0)  # Pop off the leading column

                # Check to see if we were a spinor
                if dim[0] >= self.n - 1:
                    if verbose:
                        print("====================")
                        print(
                            repr(self.rigged_con.parent()(
                                *self.cur_partitions,
                                use_vacancy_numbers=True)))
                        print("--------------------")
                        print(ret_crystal_path)
                        print("--------------------\n")
                        print("Applying halving map")
                    self.halving_map()

                    if build_graph:
                        y = self.rigged_con.parent()(
                            *[x._clone() for x in self.cur_partitions],
                            use_vacancy_numbers=True)
                        self._graph.append([
                            self._graph[-1][1], (y, len(self._graph)), '1/2x'
                        ])

        if build_graph:
            self._graph.pop(0)  # Remove the dummy at the start
            from sage.graphs.digraph import DiGraph
            from sage.graphs.dot2tex_utils import have_dot2tex
            self._graph = DiGraph(self._graph, format="list_of_edges")
            if have_dot2tex():
                self._graph.set_latex_options(format="dot2tex",
                                              edge_labels=True)

        return self.KRT(pathlist=ret_crystal_path)
        def digraph(self, subset=None, index_set=None):
            """
            Returns 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

            EXAMPLES::

                sage: C = Crystals().example(5)
                sage: C.digraph()
                Digraph on 6 vertices

            The edges of the crystal graph are by default colored using blue for edge 1, red for edge 2,
            and green for edge 3::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            One may also overwrite the colors::

                sage: C = Crystals().example(3)
                sage: G = C.digraph()
                sage: G.set_latex_options(color_by_label = {1:"red", 2:"purple", 3:"blue"})
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Or one may add colors to yet unspecified edges::

                sage: C = Crystals().example(4)
                sage: G = C.digraph()
                sage: C.cartan_type()._index_set_coloring[4]="purple"
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            Here is an example of how to take the top part up to a given depth of an infinite dimensional
            crystal::

                sage: C = CartanType(['C',2,1])
                sage: La = C.root_system().weight_lattice().fundamental_weights()
                sage: T = crystals.HighestWeight(La[0])
                sage: S = T.subcrystal(max_depth=3)
                sage: G = T.digraph(subset=S); G
                Digraph on 5 vertices
                sage: sorted(G.vertices(), key=str)
                [(-Lambda[0] + 2*Lambda[1] - delta,),
                 (1/2*Lambda[0] + Lambda[1] - Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
                 (1/2*Lambda[0] - Lambda[1] + Lambda[2] - 1/2*delta, -1/2*Lambda[0] + Lambda[1] - 1/2*delta),
                 (Lambda[0] - 2*Lambda[1] + 2*Lambda[2] - delta,),
                 (Lambda[0],)]

            Here is a way to construct a picture of a Demazure crystal using
            the ``subset`` option::

                sage: B = crystals.Tableaux(['A',2], shape=[2,1])
                sage: C = CombinatorialFreeModule(QQ,B)
                sage: t = B.highest_weight_vector()
                sage: b = C(t)
                sage: D = B.demazure_operator(b,[2,1]); D
                B[[[1, 1], [2]]] + B[[[1, 2], [2]]] + B[[[1, 3], [2]]] + B[[[1, 1], [3]]] + B[[[1, 3], [3]]]
                sage: G = B.digraph(subset=D.support())
                sage: G.vertices()
                [[[1, 1], [2]], [[1, 2], [2]], [[1, 3], [2]], [[1, 1], [3]], [[1, 3], [3]]]
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            We can also choose to display particular arrows using the
            ``index_set`` option::

                sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1)
                sage: G = C.digraph(index_set=[1,3])
                sage: len(G.edges())
                20
                sage: view(G, pdflatex=True, tightpage=True)  #optional - dot2tex graphviz

            TODO: add more tests
            """
            from sage.graphs.all import DiGraph
            from sage.categories.highest_weight_crystals import HighestWeightCrystals
            d = {}
            if self in HighestWeightCrystals:
                f = lambda u_v_label: ({})
            else:
                f = lambda u_v_label: ({"backward": u_v_label[2] == 0})

            # Parse optional arguments
            if subset is None:
                subset = self
            if index_set is None:
                index_set = self.index_set()

            for x in subset:
                d[x] = {}
                for i in index_set:
                    child = x.f(i)
                    if child is None or child not in subset:
                        continue
                    d[x][child]=i
            G = DiGraph(d)
            if have_dot2tex():
                G.set_latex_options(format="dot2tex",
                                    edge_labels = True,
                                    color_by_label = self.cartan_type()._index_set_coloring,
                                    edge_options = f)
            return G