コード例 #1
0
ファイル: isgci.py プロジェクト: BlairArchibald/sage
    def inclusion_digraph(self):
        r"""
        Returns the class inclusion digraph

        Upon the first call, this loads the database from the local
        XML file. Subsequent calls are cached.

        EXAMPLES::

            sage: g = graph_classes.inclusion_digraph(); g
            Digraph on ... vertices
        """
        classes    = self.classes()
        inclusions = self.inclusions()

        from sage.graphs.digraph import DiGraph
        inclusion_digraph = DiGraph()
        inclusion_digraph.add_vertices(classes.keys())

        for edge in inclusions:
            if edge.get("confidence","") == "unpublished":
                continue
            inclusion_digraph.add_edge(edge['super'], edge['sub'])

        return inclusion_digraph
コード例 #2
0
ファイル: suffix_trees.py プロジェクト: yarv/sage
    def uncompactify(self):
        r"""
        Returns the tree obtained from self by splitting edges so that they
        are labelled by exactly one letter. The resulting tree is
        isomorphic to the suffix trie.

        EXAMPLES::

            sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree, SuffixTrie
            sage: abbab = Words("ab")("abbab")
            sage: s = SuffixTrie(abbab)
            sage: t = ImplicitSuffixTree(abbab)
            sage: t.uncompactify().is_isomorphic(s.to_digraph())
            True
        """
        tree = self.to_digraph(word_labels=True)
        newtree = DiGraph()
        newtree.add_vertices(range(tree.order()))
        new_node = tree.order() + 1
        for (u, v, label) in tree.edge_iterator():
            if len(label) == 1:
                newtree.add_edge(u, v)
            else:
                newtree.add_edge(u, new_node, label[0])
                for w in label[1:-1]:
                    newtree.add_edge(new_node, new_node + 1, w)
                    new_node += 1
                newtree.add_edge(new_node, v, label[-1])
                new_node += 1
        return newtree
コード例 #3
0
ファイル: isgci.py プロジェクト: manguluka/sage
    def inclusion_digraph(self):
        r"""
        Returns the class inclusion digraph

        Upon the first call, this loads the database from the local
        XML file. Subsequent calls are cached.

        EXAMPLES::

            sage: g = graph_classes.inclusion_digraph(); g
            Digraph on ... vertices
        """
        classes    = self.classes()
        inclusions = self.inclusions()

        from sage.graphs.digraph import DiGraph
        inclusion_digraph = DiGraph()
        inclusion_digraph.add_vertices(classes.keys())

        for edge in inclusions:
            if edge.get("confidence","") == "unpublished":
                continue
            inclusion_digraph.add_edge(edge['super'], edge['sub'])

        return inclusion_digraph
コード例 #4
0
ファイル: suffix_trees.py プロジェクト: CETHop/sage
    def uncompactify(self):
        r"""
        Returns the tree obtained from self by splitting edges so that they
        are labelled by exactly one letter. The resulting tree is
        isomorphic to the suffix trie.

        EXAMPLES::

            sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree, SuffixTrie
            sage: abbab = Words("ab")("abbab")
            sage: s = SuffixTrie(abbab)
            sage: t = ImplicitSuffixTree(abbab)
            sage: t.uncompactify().is_isomorphic(s.to_digraph())
            True
        """
        tree = self.to_digraph(word_labels=True)
        newtree = DiGraph()
        newtree.add_vertices(range(tree.order()))
        new_node = tree.order() + 1
        for (u,v,label) in tree.edge_iterator():
            if len(label) == 1:
                newtree.add_edge(u,v)
            else:
                newtree.add_edge(u,new_node,label[0]);
                for w in label[1:-1]:
                    newtree.add_edge(new_node,new_node+1,w)
                    new_node += 1
                newtree.add_edge(new_node,v,label[-1])
                new_node += 1
        return newtree
コード例 #5
0
ファイル: supercrystals.py プロジェクト: yabirgb/sage
            def digraph(self, index_set=None):
                r"""
                Return the :class:`DiGraph` associated to ``self``.

                EXAMPLES::

                    sage: B = crystals.Letters(['A', [1,3]])
                    sage: G = B.digraph(); G
                    Multi-digraph on 6 vertices
                    sage: Q = crystals.Letters(['Q',3])
                    sage: G = Q.digraph(); G
                    Multi-digraph on 3 vertices
                    sage: G.edges()
                    [(1, 2, -1), (1, 2, 1), (2, 3, -2), (2, 3, 2)]

                The edges of the crystal graph are by default colored using
                blue for edge 1, red for edge 2, green for edge 3, and dashed with
                the corresponding color for barred edges. Edge 0 is dotted black::

                    sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)
                """
                from sage.graphs.digraph import DiGraph
                from sage.misc.latex import LatexExpr
                from sage.combinat.root_system.cartan_type import CartanType

                if index_set is None:
                    index_set = self.index_set()

                G = DiGraph(multiedges=True)
                G.add_vertices(self)
                for i in index_set:
                    for x in G:
                        y = x.f(i)
                        if y is not None:
                            G.add_edge(x, y, i)

                def edge_options(data):
                    u, v, l = data
                    edge_opts = {'edge_string': '->', 'color': 'black'}
                    if l > 0:
                        edge_opts['color'] = CartanType._colors.get(l, 'black')
                        edge_opts['label'] = LatexExpr(str(l))
                    elif l < 0:
                        edge_opts[
                            'color'] = "dashed," + CartanType._colors.get(
                                -l, 'black')
                        edge_opts['label'] = LatexExpr("\\overline{%s}" %
                                                       str(-l))
                    else:
                        edge_opts[
                            'color'] = "dotted," + CartanType._colors.get(
                                l, 'black')
                        edge_opts['label'] = LatexExpr(str(l))
                    return edge_opts

                G.set_latex_options(format="dot2tex",
                                    edge_labels=True,
                                    edge_options=edge_options)
                return G
コード例 #6
0
        def digraph(self):
            r"""
            Return the :class:`DiGraph` associated to ``self``.

            EXAMPLES::

                sage: B = crystals.Letters(['A', [1,3]])
                sage: G = B.digraph(); G
                Multi-digraph on 6 vertices
                sage: Q = crystals.Letters(['Q',3])
                sage: G = Q.digraph(); G
                Multi-digraph on 3 vertices
                sage: G.edges()
                [(1, 2, -1), (1, 2, 1), (2, 3, -2), (2, 3, 2)]

            The edges of the crystal graph are by default colored using
            blue for edge 1, red for edge 2, green for edge 3, and dashed with
            the corresponding color for barred edges. Edge 0 is dotted black::

                sage: view(G)  # optional - dot2tex graphviz, not tested (opens external window)
            """
            from sage.graphs.digraph import DiGraph
            from sage.misc.latex import LatexExpr
            from sage.combinat.root_system.cartan_type import CartanType

            G = DiGraph(multiedges=True)
            G.add_vertices(self)
            for i in self.index_set():
                for x in G:
                    y = x.f(i)
                    if y is not None:
                        G.add_edge(x, y, i)

            def edge_options(data):
                u, v, l = data
                edge_opts = { 'edge_string': '->', 'color': 'black' }
                if l > 0:
                    edge_opts['color'] = CartanType._colors.get(l, 'black')
                    edge_opts['label'] = LatexExpr(str(l))
                elif l < 0:
                    edge_opts['color'] = "dashed," + CartanType._colors.get(-l, 'black')
                    edge_opts['label'] = LatexExpr("\\overline{%s}" % str(-l))
                else:
                    edge_opts['color'] = "dotted," + CartanType._colors.get(l, 'black')
                    edge_opts['label'] = LatexExpr(str(l))
                return edge_opts

            G.set_latex_options(format="dot2tex", edge_labels=True, edge_options=edge_options)

            return G
 def quiver_v2(self):
     #if hasattr(self, "_quiver_cache"):
     #    return self._quiver_cache
     from sage.combinat.subset import Subsets
     from sage.graphs.digraph import DiGraph
     Q = DiGraph(multiedges=True)
     Q.add_vertices(self.j_transversal())
     g = self.associated_graph()
     for U in Subsets(g.vertices()):
         for W in Subsets(U):
             h = g.subgraph(U.difference(W))
             n = h.connected_components_number() - 1
             if n > 0:
                 u = self.j_class_representative(self.j_class_index(self(''.join(U))))
                 w = self.j_class_representative(self.j_class_index(self(''.join(W))))
                 for i in range(n):
                     Q.add_edge(w, u, i)
     return Q
コード例 #8
0
 def quiver_v2(self):
     #if hasattr(self, "_quiver_cache"):
     #    return self._quiver_cache
     from sage.combinat.subset import Subsets
     from sage.graphs.digraph import DiGraph
     Q = DiGraph(multiedges=True)
     Q.add_vertices(self.j_transversal())
     g = self.associated_graph()
     for U in Subsets(g.vertices()):
         for W in Subsets(U):
             h = g.subgraph(U.difference(W))
             n = h.connected_components_number() - 1
             if n > 0:
                 u = self.j_class_representative(self.j_class_index(self(''.join(U))))
                 w = self.j_class_representative(self.j_class_index(self(''.join(W))))
                 for i in range(n):
                     Q.add_edge(w, u, i)
     return Q
コード例 #9
0
    def induced_orientation(self, w):
        r"""
        The induced subgraph of the complement of the underlying graph with an
        orientation determined by `w`: an edge `(x,y)` is directed from `x` to
        `y` if `x` comes before `y` in `w`.

        EXAMPLES::

            sage: from sage_semigroups.monoids.free_partially_commutative_left_regular_band import FreePartiallyCommutativeLeftRegularBand
            sage: G = Graph({'a':['b'],'b':['d'],'c':[],'d':[]})
            sage: S = FreePartiallyCommutativeLeftRegularBand(G); S
            Free partially commutative left regular band on Graph on 4 vertices
            sage: w = S('cdab')
            sage: H = S.induced_orientation(w)
            sage: H.vertices()
            ['a', 'b', 'c', 'd']
            sage: H.edges()
            [('c', 'a', None), ('c', 'b', None), ('c', 'd', None), ('d', 'a', None)]
            sage: w = S('dab')
            sage: H = S.induced_orientation(w)
            sage: H.vertices()
            ['a', 'b', 'd']
            sage: H.edges()
            [('d', 'a', None)]

        """
        pos = dict((wi,i) for (i,wi) in enumerate(w.value))
        D = DiGraph()
        D.add_vertices(pos)
        for (u,v,l) in self.associated_graph().complement().edges():
            if u in pos and v in pos:
                if pos[u] < pos[v]:
                    D.add_edge(u,v)
                else:
                    D.add_edge(v,u)
        return D
    def induced_orientation(self, w):
        r"""
        The induced subgraph of the complement of the underlying graph with an
        orientation determined by `w`: an edge `(x,y)` is directed from `x` to
        `y` if `x` comes before `y` in `w`.

        EXAMPLES::

            sage: from sage_semigroups.monoids.free_partially_commutative_left_regular_band import FreePartiallyCommutativeLeftRegularBand
            sage: G = Graph({'a':['b'],'b':['d'],'c':[],'d':[]})
            sage: S = FreePartiallyCommutativeLeftRegularBand(G); S
            Free partially commutative left regular band on Graph on 4 vertices
            sage: w = S('cdab')
            sage: H = S.induced_orientation(w)
            sage: H.vertices()
            ['a', 'b', 'c', 'd']
            sage: H.edges()
            [('c', 'a', None), ('c', 'b', None), ('c', 'd', None), ('d', 'a', None)]
            sage: w = S('dab')
            sage: H = S.induced_orientation(w)
            sage: H.vertices()
            ['a', 'b', 'd']
            sage: H.edges()
            [('d', 'a', None)]

        """
        pos = dict((wi,i) for (i,wi) in enumerate(w.value))
        D = DiGraph()
        D.add_vertices(pos)
        for (u,v,l) in self.associated_graph().complement().edges():
            if u in pos and v in pos:
                if pos[u] < pos[v]:
                    D.add_edge(u,v)
                else:
                    D.add_edge(v,u)
        return D
コード例 #11
0
ファイル: semigroups.py プロジェクト: manguluka/sage
        def cayley_graph(self,
                         side="right",
                         simple=False,
                         elements=None,
                         generators=None,
                         connecting_set=None):
            r"""
            Return the Cayley graph for this finite semigroup.

            INPUT:

            - ``side`` -- "left", "right", or "twosided":
              the side on which the generators act (default:"right")
            - ``simple`` -- boolean (default:False):
              if True, returns a simple graph (no loops, no labels,
              no multiple edges)
            - ``generators`` -- a list, tuple, or family of elements
              of ``self`` (default: ``self.semigroup_generators()``)
            - ``connecting_set`` -- alias for ``generators``; deprecated
            - ``elements`` -- a list (or iterable) of elements of ``self``

            OUTPUT:

            - :class:`DiGraph`

            EXAMPLES:

            We start with the (right) Cayley graphs of some classical groups::

                sage: D4 = DihedralGroup(4); D4
                Dihedral group of order 8 as a permutation group
                sage: G = D4.cayley_graph()
                sage: show(G, color_by_label=True, edge_labels=True)
                sage: A5 = AlternatingGroup(5); A5
                Alternating group of order 5!/2 as a permutation group
                sage: G = A5.cayley_graph()
                sage: G.show3d(color_by_label=True, edge_size=0.01, edge_size2=0.02, vertex_size=0.03)
                sage: G.show3d(vertex_size=0.03, edge_size=0.01, edge_size2=0.02, vertex_colors={(1,1,1):G.vertices()}, bgcolor=(0,0,0), color_by_label=True, xres=700, yres=700, iterations=200) # long time (less than a minute)
                sage: G.num_edges()
                120

                sage: w = WeylGroup(['A',3])
                sage: d = w.cayley_graph(); d
                Digraph on 24 vertices
                sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03)

            Alternative generators may be specified::

                sage: G = A5.cayley_graph(generators=[A5.gens()[0]])
                sage: G.num_edges()
                60
                sage: g=PermutationGroup([(i+1,j+1) for i in range(5) for j in range(5) if j!=i])
                sage: g.cayley_graph(generators=[(1,2),(2,3)])
                Digraph on 120 vertices

            If ``elements`` is specified, then only the subgraph
            induced and those elements is returned. Here we use it to
            display the Cayley graph of the free monoid truncated on
            the elements of length at most 3::

                sage: M = Monoids().example(); M
                An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd')
                sage: elements = [ M.prod(w) for w in sum((list(Words(M.semigroup_generators(),k)) for k in range(4)),[]) ]
                sage: G = M.cayley_graph(elements = elements)
                sage: G.num_verts(), G.num_edges()
                (85, 84)
                sage: G.show3d(color_by_label=True, edge_size=0.001, vertex_size=0.01)

            We now illustrate the ``side`` and ``simple`` options on
            a semigroup::

                sage: S = FiniteSemigroups().example(alphabet=('a','b'))
                sage: g = S.cayley_graph(simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ab', None), ('b', 'ba', None)]

            ::

                sage: g = S.cayley_graph(side="left", simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None),
                ('ba', 'ab', None)]

            ::

                sage: g = S.cayley_graph(side="twosided", simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ab', None), ('a', 'ba', None), ('ab', 'ba', None),
                ('b', 'ab', None), ('b', 'ba', None), ('ba', 'ab', None)]

            ::

                sage: g = S.cayley_graph(side="twosided")
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'a', (0, 'left')), ('a', 'a', (0, 'right')), ('a', 'ab', (1, 'right')), ('a', 'ba', (1, 'left')), ('ab', 'ab', (0, 'left')), ('ab', 'ab', (0, 'right')), ('ab', 'ab', (1, 'right')), ('ab', 'ba', (1, 'left')), ('b', 'ab', (0, 'left')), ('b', 'b', (1, 'left')), ('b', 'b', (1, 'right')), ('b', 'ba', (0, 'right')), ('ba', 'ab', (0, 'left')), ('ba', 'ba', (0, 'right')), ('ba', 'ba', (1, 'left')), ('ba', 'ba', (1, 'right'))]

            ::

                sage: s1 = SymmetricGroup(1); s = s1.cayley_graph(); s.vertices()
                [()]

            TESTS::

                sage: SymmetricGroup(2).cayley_graph(side="both")
                Traceback (most recent call last):
                ...
                ValueError: option 'side' must be 'left', 'right' or 'twosided'

            .. TODO::

                - Add more options for constructing subgraphs of the
                  Cayley graph, handling the standard use cases when
                  exploring large/infinite semigroups (a predicate,
                  generators of an ideal, a maximal length in term of the
                  generators)

                - Specify good default layout/plot/latex options in the graph

                - Generalize to combinatorial modules with module generators / operators

            AUTHORS:

            - Bobby Moretti (2007-08-10)
            - Robert Miller (2008-05-01): editing
            - Nicolas M. Thiery (2008-12): extension to semigroups,
              ``side``, ``simple``, and ``elements`` options, ...
            """
            from sage.graphs.digraph import DiGraph
            from monoids import Monoids
            from groups import Groups
            if not side in ["left", "right", "twosided"]:
                raise ValueError(
                    "option 'side' must be 'left', 'right' or 'twosided'")
            if elements is None:
                assert self.is_finite(
                ), "elements should be specified for infinite semigroups"
                elements = self
            else:
                elements = set(elements)
            if simple or self in Groups():
                result = DiGraph()
            else:
                result = DiGraph(multiedges=True, loops=True)
            result.add_vertices(elements)

            if connecting_set is not None:
                generators = connecting_set
            if generators is None:
                if self in Monoids and hasattr(self, "monoid_generators"):
                    generators = self.monoid_generators()
                else:
                    generators = self.semigroup_generators()
            if isinstance(generators, (list, tuple)):
                generators = dict((self(g), self(g)) for g in generators)
            left = (side == "left" or side == "twosided")
            right = (side == "right" or side == "twosided")

            def add_edge(source, target, label, side_label):
                """
                Skips edges whose targets are not in elements
                Return an appropriate edge given the options
                """
                if (elements is not self and target not in elements):
                    return
                if simple:
                    result.add_edge([source, target])
                elif side == "twosided":
                    result.add_edge([source, target, (label, side_label)])
                else:
                    result.add_edge([source, target, label])

            for x in elements:
                for i in generators.keys():
                    if left:
                        add_edge(x, generators[i] * x, i, "left")
                    if right:
                        add_edge(x, x * generators[i], i, "right")
            return result
コード例 #12
0
ファイル: poset_examples.py プロジェクト: bukzor/sage
    def RandomPoset(n,p):
        r"""
        Generate a random poset on ``n`` vertices according to a
        probability ``p``.

        INPUT:

        - ``n`` - number of vertices, a non-negative integer

        - ``p`` - a probability, a real number between 0 and 1 (inclusive)

        OUTPUT:

        A poset on ``n`` vertices.  The construction decides to make an
        ordered pair of vertices comparable in the poset with probability
        ``p``, however a pair is not made comparable if it would violate
        the defining properties of a poset, such as transitivity.

        So in practice, once the probability exceeds a small number the
        generated posets may be very similar to a chain.  So to create
        interesting examples, keep the probability small, perhaps on the
        order of `1/n`.

        EXAMPLES::

            sage: Posets.RandomPoset(17,.15)
            Finite poset containing 17 elements

        TESTS::

            sage: Posets.RandomPoset('junk', 0.5)
            Traceback (most recent call last):
            ...
            TypeError: number of elements must be an integer, not junk

            sage: Posets.RandomPoset(-6, 0.5)
            Traceback (most recent call last):
            ...
            ValueError: number of elements must be non-negative, not -6

            sage: Posets.RandomPoset(6, 'garbage')
            Traceback (most recent call last):
            ...
            TypeError: probability must be a real number, not garbage

            sage: Posets.RandomPoset(6, -0.5)
            Traceback (most recent call last):
            ...
            ValueError: probability must be between 0 and 1, not -0.5
        """
        from sage.misc.prandom import random
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError("number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError("number of elements must be non-negative, not {0}".format(n))
        try:
            p = float(p)
        except Exception:
            raise TypeError("probability must be a real number, not {0}".format(p))
        if p < 0 or p> 1:
            raise ValueError("probability must be between 0 and 1, not {0}".format(p))

        D = DiGraph(loops=False,multiedges=False)
        D.add_vertices(range(n))
        for i in range(n):
            for j in range(n):
                if random() < p:
                    D.add_edge(i,j)
                    if not D.is_directed_acyclic():
                        D.delete_edge(i,j)
        return Poset(D,cover_relations=False)
コード例 #13
0
    def RandomPoset(n,p):
        r"""
        Generate a random poset on ``n`` vertices according to a
        probability ``p``.

        INPUT:

        - ``n`` - number of vertices, a non-negative integer

        - ``p`` - a probability, a real number between 0 and 1 (inclusive)

        OUTPUT:

        A poset on ``n`` vertices.  The construction decides to make an
        ordered pair of vertices comparable in the poset with probability
        ``p``, however a pair is not made comparable if it would violate
        the defining properties of a poset, such as transitivity.

        So in practice, once the probability exceeds a small number the
        generated posets may be very similar to a chain.  So to create
        interesting examples, keep the probability small, perhaps on the
        order of `1/n`.

        EXAMPLES::

            sage: Posets.RandomPoset(17,.15)
            Finite poset containing 17 elements

        TESTS::

            sage: Posets.RandomPoset('junk', 0.5)
            Traceback (most recent call last):
            ...
            TypeError: number of elements must be an integer, not junk

            sage: Posets.RandomPoset(-6, 0.5)
            Traceback (most recent call last):
            ...
            ValueError: number of elements must be non-negative, not -6

            sage: Posets.RandomPoset(6, 'garbage')
            Traceback (most recent call last):
            ...
            TypeError: probability must be a real number, not garbage

            sage: Posets.RandomPoset(6, -0.5)
            Traceback (most recent call last):
            ...
            ValueError: probability must be between 0 and 1, not -0.5
        """
        from sage.misc.prandom import random
        try:
            n = Integer(n)
        except TypeError:
            raise TypeError("number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError("number of elements must be non-negative, not {0}".format(n))
        try:
            p = float(p)
        except Exception:
            raise TypeError("probability must be a real number, not {0}".format(p))
        if p < 0 or p> 1:
            raise ValueError("probability must be between 0 and 1, not {0}".format(p))

        D = DiGraph(loops=False,multiedges=False)
        D.add_vertices(range(n))
        for i in range(n):
            for j in range(n):
                if random() < p:
                    D.add_edge(i,j)
                    if not D.is_directed_acyclic():
                        D.delete_edge(i,j)
        return Poset(D,cover_relations=False)
コード例 #14
0
ファイル: semigroups.py プロジェクト: sensen1/sage
        def cayley_graph(self, side="right", simple=False, elements = None, generators = None, connecting_set = None):
            r"""
            Return the Cayley graph for this finite semigroup.

            INPUT:

            - ``side`` -- "left", "right", or "twosided":
              the side on which the generators act (default:"right")
            - ``simple`` -- boolean (default:False):
              if True, returns a simple graph (no loops, no labels,
              no multiple edges)
            - ``generators`` -- a list, tuple, or family of elements
              of ``self`` (default: ``self.semigroup_generators()``)
            - ``connecting_set`` -- alias for ``generators``; deprecated
            - ``elements`` -- a list (or iterable) of elements of ``self``

            OUTPUT:

            - :class:`DiGraph`

            EXAMPLES:

            We start with the (right) Cayley graphs of some classical groups::

                sage: D4 = DihedralGroup(4); D4
                Dihedral group of order 8 as a permutation group
                sage: G = D4.cayley_graph()
                sage: show(G, color_by_label=True, edge_labels=True)
                sage: A5 = AlternatingGroup(5); A5
                Alternating group of order 5!/2 as a permutation group
                sage: G = A5.cayley_graph()
                sage: G.show3d(color_by_label=True, edge_size=0.01, edge_size2=0.02, vertex_size=0.03)
                sage: G.show3d(vertex_size=0.03, edge_size=0.01, edge_size2=0.02, vertex_colors={(1,1,1):G.vertices()}, bgcolor=(0,0,0), color_by_label=True, xres=700, yres=700, iterations=200) # long time (less than a minute)
                sage: G.num_edges()
                120

                sage: w = WeylGroup(['A',3])
                sage: d = w.cayley_graph(); d
                Digraph on 24 vertices
                sage: d.show3d(color_by_label=True, edge_size=0.01, vertex_size=0.03)

            Alternative generators may be specified::

                sage: G = A5.cayley_graph(generators=[A5.gens()[0]])
                sage: G.num_edges()
                60
                sage: g=PermutationGroup([(i+1,j+1) for i in range(5) for j in range(5) if j!=i])
                sage: g.cayley_graph(generators=[(1,2),(2,3)])
                Digraph on 120 vertices

            If ``elements`` is specified, then only the subgraph
            induced and those elements is returned. Here we use it to
            display the Cayley graph of the free monoid truncated on
            the elements of length at most 3::

                sage: M = Monoids().example(); M
                An example of a monoid: the free monoid generated by ('a', 'b', 'c', 'd')
                sage: elements = [ M.prod(w) for w in sum((list(Words(M.semigroup_generators(),k)) for k in range(4)),[]) ]
                sage: G = M.cayley_graph(elements = elements)
                sage: G.num_verts(), G.num_edges()
                (85, 84)
                sage: G.show3d(color_by_label=True, edge_size=0.001, vertex_size=0.01)

            We now illustrate the ``side`` and ``simple`` options on
            a semigroup::

                sage: S = FiniteSemigroups().example(alphabet=('a','b'))
                sage: g = S.cayley_graph(simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ab', None), ('b', 'ba', None)]

            ::

                sage: g = S.cayley_graph(side="left", simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ba', None), ('ab', 'ba', None), ('b', 'ab', None),
                ('ba', 'ab', None)]

            ::

                sage: g = S.cayley_graph(side="twosided", simple=True)
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'ab', None), ('a', 'ba', None), ('ab', 'ba', None),
                ('b', 'ab', None), ('b', 'ba', None), ('ba', 'ab', None)]

            ::

                sage: g = S.cayley_graph(side="twosided")
                sage: g.vertices()
                ['a', 'ab', 'b', 'ba']
                sage: g.edges()
                [('a', 'a', (0, 'left')), ('a', 'a', (0, 'right')), ('a', 'ab', (1, 'right')), ('a', 'ba', (1, 'left')), ('ab', 'ab', (0, 'left')), ('ab', 'ab', (0, 'right')), ('ab', 'ab', (1, 'right')), ('ab', 'ba', (1, 'left')), ('b', 'ab', (0, 'left')), ('b', 'b', (1, 'left')), ('b', 'b', (1, 'right')), ('b', 'ba', (0, 'right')), ('ba', 'ab', (0, 'left')), ('ba', 'ba', (0, 'right')), ('ba', 'ba', (1, 'left')), ('ba', 'ba', (1, 'right'))]

            ::

                sage: s1 = SymmetricGroup(1); s = s1.cayley_graph(); s.vertices()
                [()]

            TESTS::

                sage: SymmetricGroup(2).cayley_graph(side="both")
                Traceback (most recent call last):
                ...
                ValueError: option 'side' must be 'left', 'right' or 'twosided'

            .. TODO::

                - Add more options for constructing subgraphs of the
                  Cayley graph, handling the standard use cases when
                  exploring large/infinite semigroups (a predicate,
                  generators of an ideal, a maximal length in term of the
                  generators)

                - Specify good default layout/plot/latex options in the graph

                - Generalize to combinatorial modules with module generators / operators

            AUTHORS:

            - Bobby Moretti (2007-08-10)
            - Robert Miller (2008-05-01): editing
            - Nicolas M. Thiery (2008-12): extension to semigroups,
              ``side``, ``simple``, and ``elements`` options, ...
            """
            from sage.graphs.digraph import DiGraph
            from monoids import Monoids
            from groups import Groups
            if not side in ["left", "right", "twosided"]:
                raise ValueError("option 'side' must be 'left', 'right' or 'twosided'")
            if elements is None:
                assert self.is_finite(), "elements should be specified for infinite semigroups"
                elements = self
            else:
                elements = set(elements)
            if simple or self in Groups():
                result = DiGraph()
            else:
                result = DiGraph(multiedges = True, loops = True)
            result.add_vertices(elements)

            if connecting_set is not None:
                generators = connecting_set
            if generators is None:
                if self in Monoids and hasattr(self, "monoid_generators"):
                    generators = self.monoid_generators()
                else:
                    generators = self.semigroup_generators()
            if isinstance(generators, (list, tuple)):
                generators = dict((self(g), self(g)) for g in generators)
            left  = (side == "left"  or side == "twosided")
            right = (side == "right" or side == "twosided")
            def add_edge(source, target, label, side_label):
                """
                Skips edges whose targets are not in elements
                Return an appropriate edge given the options
                """
                if (elements is not self and
                    target not in elements):
                    return
                if simple:
                    result.add_edge([source, target])
                elif side == "twosided":
                    result.add_edge([source, target, (label, side_label)])
                else:
                    result.add_edge([source, target, label])
            for x in elements:
                for i in generators.keys():
                    if left:
                        add_edge(x, generators[i]*x, i, "left" )
                    if right:
                        add_edge(x, x*generators[i], i, "right")
            return result
コード例 #15
0
ファイル: poset_examples.py プロジェクト: Babyll/sage
    def RandomPoset(n, p):
        r"""
        Generate a random poset on ``n`` elements according to a
        probability ``p``.

        INPUT:

        - ``n`` - number of elements, a non-negative integer

        - ``p`` - a probability, a real number between 0 and 1 (inclusive)

        OUTPUT:

        A poset on `n` elements. The probability `p` roughly measures
        width/height of the output: `p=0` always generates an antichain,
        `p=1` will return a chain. To create interesting examples,
        keep the probability small, perhaps on the order of `1/n`.

        EXAMPLES::

            sage: set_random_seed(0)  # Results are reproducible
            sage: P = Posets.RandomPoset(5, 0.3)
            sage: P.cover_relations()
            [[5, 4], [4, 2], [1, 2]]

        TESTS::

            sage: Posets.RandomPoset('junk', 0.5)
            Traceback (most recent call last):
            ...
            TypeError: number of elements must be an integer, not junk

            sage: Posets.RandomPoset(-6, 0.5)
            Traceback (most recent call last):
            ...
            ValueError: number of elements must be non-negative, not -6

            sage: Posets.RandomPoset(6, 'garbage')
            Traceback (most recent call last):
            ...
            TypeError: probability must be a real number, not garbage

            sage: Posets.RandomPoset(6, -0.5)
            Traceback (most recent call last):
            ...
            ValueError: probability must be between 0 and 1, not -0.5

            sage: Posets.RandomPoset(0, 0.5)
            Finite poset containing 0 elements
        """
        from sage.misc.prandom import random

        try:
            n = Integer(n)
        except TypeError:
            raise TypeError("number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError("number of elements must be non-negative, not {0}".format(n))
        try:
            p = float(p)
        except Exception:
            raise TypeError("probability must be a real number, not {0}".format(p))
        if p < 0 or p> 1:
            raise ValueError("probability must be between 0 and 1, not {0}".format(p))

        D = DiGraph(loops=False, multiedges=False)
        D.add_vertices(range(n))
        for i in range(n):
            for j in range(i+1, n):
                if random() < p:
                    D.add_edge(i, j)
        D.relabel(list(Permutations(n).random_element()))
        return Poset(D, cover_relations=False)
コード例 #16
0
def line_graph(self, labels=True):
    """
    Returns the line graph of the (di)graph.

    INPUT:

    - ``labels`` (boolean) -- whether edge labels should be taken in
      consideration. If ``labels=True``, the vertices of the line graph will be
      triples ``(u,v,label)``, and pairs of vertices otherwise.

      This is set to ``True`` by default.

    The line graph of an undirected graph G is an undirected graph H such that
    the vertices of H are the edges of G and two vertices e and f of H are
    adjacent if e and f share a common vertex in G. In other words, an edge in H
    represents a path of length 2 in G.

    The line graph of a directed graph G is a directed graph H such that the
    vertices of H are the edges of G and two vertices e and f of H are adjacent
    if e and f share a common vertex in G and the terminal vertex of e is the
    initial vertex of f. In other words, an edge in H represents a (directed)
    path of length 2 in G.

    .. NOTE::

        As a :class:`Graph` object only accepts hashable objects as vertices
        (and as the vertices of the line graph are the edges of the graph), this
        code will fail if edge labels are not hashable. You can also set the
        argument ``labels=False`` to ignore labels.

    .. SEEALSO::

        - The :mod:`line_graph <sage.graphs.line_graph>` module.

        - :meth:`~sage.graphs.graph_generators.GraphGenerators.line_graph_forbidden_subgraphs`
          -- the forbidden subgraphs of a line graph.

        - :meth:`~Graph.is_line_graph` -- tests whether a graph is a line graph.

    EXAMPLES::

        sage: g = graphs.CompleteGraph(4)
        sage: h = g.line_graph()
        sage: h.vertices()
        [(0, 1, None),
        (0, 2, None),
        (0, 3, None),
        (1, 2, None),
        (1, 3, None),
        (2, 3, None)]
        sage: h.am()
        [0 1 1 1 1 0]
        [1 0 1 1 0 1]
        [1 1 0 0 1 1]
        [1 1 0 0 1 1]
        [1 0 1 1 0 1]
        [0 1 1 1 1 0]
        sage: h2 = g.line_graph(labels=False)
        sage: h2.vertices()
        [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
        sage: h2.am() == h.am()
        True
        sage: g = DiGraph([[1..4],lambda i,j: i<j])
        sage: h = g.line_graph()
        sage: h.vertices()
        [(1, 2, None),
        (1, 3, None),
        (1, 4, None),
        (2, 3, None),
        (2, 4, None),
        (3, 4, None)]
        sage: h.edges()
        [((1, 2, None), (2, 3, None), None),
         ((1, 2, None), (2, 4, None), None),
         ((1, 3, None), (3, 4, None), None),
         ((2, 3, None), (3, 4, None), None)]

    Tests:

    :trac:`13787`::

        sage: g = graphs.KneserGraph(7,1)
        sage: C = graphs.CompleteGraph(7)
        sage: C.is_isomorphic(g)
        True
        sage: C.line_graph().is_isomorphic(g.line_graph())
        True
    """
    self._scream_if_not_simple()
    if self._directed:
        from sage.graphs.digraph import DiGraph
        G = DiGraph()
        G.add_vertices(self.edges(labels=labels))
        for v in self:
            # Connect appropriate incident edges of the vertex v
            G.add_edges([(e,f) for e in self.incoming_edge_iterator(v, labels=labels) \
                         for f in self.outgoing_edge_iterator(v, labels=labels)])
        return G
    else:
        from sage.graphs.all import Graph
        G = Graph()

        # We must sort the edges' endpoints so that (1,2,None) is seen as
        # the same edge as (2,1,None).
        #
        # We do so by comparing hashes, just in case all the natural order
        # (<) on vertices would not be a total order (for instance when
        # vertices are sets). If two adjacent vertices have the same hash,
        # then we store the pair in the dictionary of conflicts

        conflicts = {}

        # 1) List of vertices in the line graph
        elist = []
        for e in self.edge_iterator(labels=labels):
            if hash(e[0]) < hash(e[1]):
                elist.append(e)
            elif hash(e[0]) > hash(e[1]):
                elist.append((e[1], e[0]) + e[2:])
            else:
                # Settle the conflict arbitrarily
                conflicts[e] = e
                conflicts[(e[1], e[0]) + e[2:]] = e
                elist.append(e)

        G.add_vertices(elist)

        # 2) adjacencies in the line graph
        for v in self:
            elist = []

            # Add the edge to the list, according to hashes, as previously
            for e in self.edge_iterator(v, labels=labels):
                if hash(e[0]) < hash(e[1]):
                    elist.append(e)
                elif hash(e[0]) > hash(e[1]):
                    elist.append((e[1], e[0]) + e[2:])
                else:
                    elist.append(conflicts[e])

            # Alls pairs of elements in elist are edges of the
            # line graph
            while elist:
                x = elist.pop()
                for y in elist:
                    G.add_edge(x, y)

        return G
コード例 #17
0
ファイル: poset_examples.py プロジェクト: ipozdnyakov/sage
    def RandomPoset(n, p):
        r"""
        Generate a random poset on ``n`` elements according to a
        probability ``p``.

        INPUT:

        - ``n`` - number of elements, a non-negative integer

        - ``p`` - a probability, a real number between 0 and 1 (inclusive)

        OUTPUT:

        A poset on `n` elements. The probability `p` roughly measures
        width/height of the output: `p=0` always generates an antichain,
        `p=1` will return a chain. To create interesting examples,
        keep the probability small, perhaps on the order of `1/n`.

        EXAMPLES::

            sage: set_random_seed(0)  # Results are reproducible
            sage: P = Posets.RandomPoset(5, 0.3)
            sage: P.cover_relations()
            [[5, 4], [4, 2], [1, 2]]

        TESTS::

            sage: Posets.RandomPoset('junk', 0.5)
            Traceback (most recent call last):
            ...
            TypeError: number of elements must be an integer, not junk

            sage: Posets.RandomPoset(-6, 0.5)
            Traceback (most recent call last):
            ...
            ValueError: number of elements must be non-negative, not -6

            sage: Posets.RandomPoset(6, 'garbage')
            Traceback (most recent call last):
            ...
            TypeError: probability must be a real number, not garbage

            sage: Posets.RandomPoset(6, -0.5)
            Traceback (most recent call last):
            ...
            ValueError: probability must be between 0 and 1, not -0.5

            sage: Posets.RandomPoset(0, 0.5)
            Finite poset containing 0 elements
        """
        from sage.misc.prandom import random

        try:
            n = Integer(n)
        except TypeError:
            raise TypeError(
                "number of elements must be an integer, not {0}".format(n))
        if n < 0:
            raise ValueError(
                "number of elements must be non-negative, not {0}".format(n))
        try:
            p = float(p)
        except Exception:
            raise TypeError(
                "probability must be a real number, not {0}".format(p))
        if p < 0 or p > 1:
            raise ValueError(
                "probability must be between 0 and 1, not {0}".format(p))

        D = DiGraph(loops=False, multiedges=False)
        D.add_vertices(range(n))
        for i in range(n):
            for j in range(i + 1, n):
                if random() < p:
                    D.add_edge(i, j)
        D.relabel(list(Permutations(n).random_element()))
        return Poset(D, cover_relations=False)
コード例 #18
0
        def cayley_graph(self, simple = False, elements = None, generators = None):
            """
            Return the Cayley graph of ``self``

            EXAMPLES::

                sage: M = Semigroups().SetsWithAction().example(); M
                Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication
                sage: G = M.cayley_graph()
                sage: G.edges()
                [(0, 0, 2), (0, 0, 3), (1, 2, 2), (1, 3, 3),
                 (2, 4, 2), (2, 6, 3), (3, 6, 2), (3, 9, 3),
                 (4, 2, 3), (4, 8, 2), (5, 0, 2), (5, 5, 3),
                 (6, 2, 2), (6, 8, 3), (7, 1, 3), (7, 4, 2),
                 (8, 4, 3), (8, 6, 2), (9, 7, 3), (9, 8, 2)]

            Let us look at the graph::

                sage: G.set_latex_options(format='dot2tex', edge_labels=True)  # optional - requires dot2tex and graphviz
                sage: view(G, tightpage=True, pdflatex=True)                   # optional - requires dot2tex and graphviz

            The Cayley graph as a simple graph (no loops, no labels)::

                sage: G = M.cayley_graph(simple=True)
                sage: G.edges()
                [(1, 2, None), (1, 3, None),
                 (2, 4, None), (2, 6, None), (3, 6, None), (3, 9, None),
                 (4, 2, None), (4, 8, None), (5, 0, None),
                 (6, 2, None), (6, 8, None), (7, 1, None), (7, 4, None),
                 (8, 4, None), (8, 6, None), (9, 7, None), (9, 8, None)]
            """
            # This is duplicated from semigroups.cayley_graph
            from sage.graphs.digraph import DiGraph
            if elements is None:
                assert self._set.is_finite(), "elements should be specified for infinite modules"
                elements = tuple(self._set)
            elements_set = set(elements)
            if simple:
                result = DiGraph()
            else:
                result = DiGraph(multiedges = True, loops = True)
            result.add_vertices(elements)

            if generators is None:
                generators = self.semigroup().semigroup_generators()
            if isinstance(generators, (list, tuple)):
                generators = dict((self(g), self(g)) for g in generators)
            def add_edge(source, target, label):
                """
                Skips edges whose targets are not in elements
                Return an appropriate edge given the options
                """
                if target not in elements_set: return
                if simple:
                    if source != target:
                        result.add_edge([source, target])
                else:
                    result.add_edge([source, target, label])
            for x in elements:
                for i in generators.keys():
                    add_edge(x, self._action(generators[i],x), i)
            return result
コード例 #19
0
ファイル: line_graph.py プロジェクト: mcognetta/sage
def line_graph(self, labels=True):
    """
    Returns the line graph of the (di)graph.

    INPUT:

    - ``labels`` (boolean) -- whether edge labels should be taken in
      consideration. If ``labels=True``, the vertices of the line graph will be
      triples ``(u,v,label)``, and pairs of vertices otherwise.

      This is set to ``True`` by default.

    The line graph of an undirected graph G is an undirected graph H such that
    the vertices of H are the edges of G and two vertices e and f of H are
    adjacent if e and f share a common vertex in G. In other words, an edge in H
    represents a path of length 2 in G.

    The line graph of a directed graph G is a directed graph H such that the
    vertices of H are the edges of G and two vertices e and f of H are adjacent
    if e and f share a common vertex in G and the terminal vertex of e is the
    initial vertex of f. In other words, an edge in H represents a (directed)
    path of length 2 in G.

    .. NOTE::

        As a :class:`Graph` object only accepts hashable objects as vertices
        (and as the vertices of the line graph are the edges of the graph), this
        code will fail if edge labels are not hashable. You can also set the
        argument ``labels=False`` to ignore labels.

    .. SEEALSO::

        - The :mod:`line_graph <sage.graphs.line_graph>` module.

        - :meth:`~sage.graphs.graph_generators.GraphGenerators.line_graph_forbidden_subgraphs`
          -- the forbidden subgraphs of a line graph.

        - :meth:`~Graph.is_line_graph` -- tests whether a graph is a line graph.

    EXAMPLES::

        sage: g = graphs.CompleteGraph(4)
        sage: h = g.line_graph()
        sage: h.vertices()
        [(0, 1, None),
        (0, 2, None),
        (0, 3, None),
        (1, 2, None),
        (1, 3, None),
        (2, 3, None)]
        sage: h.am()
        [0 1 1 1 1 0]
        [1 0 1 1 0 1]
        [1 1 0 0 1 1]
        [1 1 0 0 1 1]
        [1 0 1 1 0 1]
        [0 1 1 1 1 0]
        sage: h2 = g.line_graph(labels=False)
        sage: h2.vertices()
        [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
        sage: h2.am() == h.am()
        True
        sage: g = DiGraph([[1..4],lambda i,j: i<j])
        sage: h = g.line_graph()
        sage: h.vertices()
        [(1, 2, None),
        (1, 3, None),
        (1, 4, None),
        (2, 3, None),
        (2, 4, None),
        (3, 4, None)]
        sage: h.edges()
        [((1, 2, None), (2, 3, None), None),
         ((1, 2, None), (2, 4, None), None),
         ((1, 3, None), (3, 4, None), None),
         ((2, 3, None), (3, 4, None), None)]

    Tests:

    :trac:`13787`::

        sage: g = graphs.KneserGraph(7,1)
        sage: C = graphs.CompleteGraph(7)
        sage: C.is_isomorphic(g)
        True
        sage: C.line_graph().is_isomorphic(g.line_graph())
        True
    """
    self._scream_if_not_simple()
    if self._directed:
        from sage.graphs.digraph import DiGraph
        G=DiGraph()
        G.add_vertices(self.edges(labels=labels))
        for v in self:
            # Connect appropriate incident edges of the vertex v
            G.add_edges([(e,f) for e in self.incoming_edge_iterator(v, labels=labels) \
                         for f in self.outgoing_edge_iterator(v, labels=labels)])
        return G
    else:
        from sage.graphs.all import Graph
        G=Graph()

        # We must sort the edges' endpoints so that (1,2,None) is seen as
        # the same edge as (2,1,None).
        #
        # We do so by comparing hashes, just in case all the natural order
        # (<) on vertices would not be a total order (for instance when
        # vertices are sets). If two adjacent vertices have the same hash,
        # then we store the pair in the dictionary of conflicts

        conflicts = {}

        # 1) List of vertices in the line graph
        elist = []
        for e in self.edge_iterator(labels = labels):
            if hash(e[0]) < hash(e[1]):
                elist.append(e)
            elif hash(e[0]) > hash(e[1]):
                elist.append((e[1],e[0])+e[2:])
            else:
                # Settle the conflict arbitrarily
                conflicts[e] = e
                conflicts[(e[1],e[0])+e[2:]] = e
                elist.append(e)

        G.add_vertices(elist)

        # 2) adjacencies in the line graph
        for v in self:
            elist = []

            # Add the edge to the list, according to hashes, as previously
            for e in self.edge_iterator(v, labels=labels):
                if hash(e[0]) < hash(e[1]):
                    elist.append(e)
                elif hash(e[0]) > hash(e[1]):
                    elist.append((e[1],e[0])+e[2:])
                else:
                    elist.append(conflicts[e])

            # Alls pairs of elements in elist are edges of the
            # line graph
            while elist:
                x = elist.pop()
                for y in elist:
                    G.add_edge(x,y)

        return G