Ejemplo n.º 1
0
    def tree(self):
        r"""
        Returns the Huffman tree corresponding to the current encoding.

        INPUT:

        - None.

        OUTPUT:

        - The binary tree representing a Huffman code.

        EXAMPLES::

            sage: from sage.coding.source_coding.huffman import Huffman
            sage: str = "Sage is my most favorite general purpose computer algebra system"
            sage: h = Huffman(str)
            sage: T = h.tree(); T
            Digraph on 39 vertices
            sage: T.show(figsize=[20,20])
            <BLANKLINE>
        """
        from sage.graphs.digraph import DiGraph
        g = DiGraph()
        g.add_edges(self._generate_edges(self._tree))
        return g
Ejemplo n.º 2
0
    def Circuit(self, n):
        r"""
        Returns the circuit on `n` vertices

        The circuit is an oriented ``CycleGraph``

        EXAMPLE:

        A circuit is the smallest strongly connected digraph::

            sage: circuit = digraphs.Circuit(15)
            sage: len(circuit.strongly_connected_components()) == 1
            True
        """
        g = DiGraph(n)
        g.name("Circuit")

        if n == 0:
            return g
        elif n == 1:
            g.allow_loops(True)
            g.add_edge(0, 0)
            return g
        else:
            g.add_edges([(i, i + 1) for i in xrange(n - 1)])
            g.add_edge(n - 1, 0)
            return g
Ejemplo n.º 3
0
    def tree(self):
        r"""
        Returns the Huffman tree corresponding to the current encoding.

        INPUT:

        - None.

        OUTPUT:

        - The binary tree representing a Huffman code.

        EXAMPLES::

            sage: from sage.coding.source_coding.huffman import Huffman
            sage: str = "Sage is my most favorite general purpose computer algebra system"
            sage: h = Huffman(str)
            sage: T = h.tree(); T
            Digraph on 39 vertices
            sage: T.show(figsize=[20,20])
            <BLANKLINE>
        """
        from sage.graphs.digraph import DiGraph
        g = DiGraph()
        g.add_edges(self._generate_edges(self._tree))
        return g
Ejemplo n.º 4
0
    def Circuit(self, n):
        r"""
        Returns the circuit on `n` vertices

        The circuit is an oriented ``CycleGraph``

        EXAMPLE:

        A circuit is the smallest strongly connected digraph::

            sage: circuit = digraphs.Circuit(15)
            sage: len(circuit.strongly_connected_components()) == 1
            True
        """
        if n < 0:
            raise ValueError(
                "The number of vertices must be a positive integer.")

        g = DiGraph()
        g.name("Circuit on " + str(n) + " vertices")

        if n == 0:
            return g
        elif n == 1:
            g.allow_loops(True)
            g.add_edge(0, 0)
            return g
        else:
            g.add_edges([(i, i + 1) for i in xrange(n - 1)])
            g.add_edge(n - 1, 0)
            return g
Ejemplo n.º 5
0
    def Circuit(self,n):
        r"""
        Returns the circuit on `n` vertices

        The circuit is an oriented ``CycleGraph``

        EXAMPLE:

        A circuit is the smallest strongly connected digraph::

            sage: circuit = digraphs.Circuit(15)
            sage: len(circuit.strongly_connected_components()) == 1
            True
        """
        g = DiGraph(n)
        g.name("Circuit")

        if n==0:
            return g
        elif n == 1:
            g.allow_loops(True)
            g.add_edge(0,0)
            return g
        else:
            g.add_edges([(i,i+1) for i in xrange(n-1)])
            g.add_edge(n-1,0)
            return g
Ejemplo n.º 6
0
    def Circuit(self,n):
        r"""
        Returns the circuit on `n` vertices

        The circuit is an oriented ``CycleGraph``

        EXAMPLE:

        A circuit is the smallest strongly connected digraph::

            sage: circuit = digraphs.Circuit(15)
            sage: len(circuit.strongly_connected_components()) == 1
            True
        """
        if n<0:
            raise ValueError("The number of vertices must be a positive integer.")

        g = DiGraph()
        g.name("Circuit on "+str(n)+" vertices")

        if n==0:
            return g
        elif n == 1:
            g.allow_loops(True)
            g.add_edge(0,0)
            return g
        else:
            g.add_edges([(i,i+1) for i in xrange(n-1)])
            g.add_edge(n-1,0)
            return g        
Ejemplo n.º 7
0
    def Circulant(self, n, integers):
        r"""
        Returns a circulant digraph on `n` vertices from a set of integers.

        INPUT:

        - ``n`` (integer) -- number of vertices.

        - ``integers`` -- the list of integers such that there is an edge from
          `i` to `j` if and only if ``(j-i)%n in integers``.

        EXAMPLE::

            sage: digraphs.Circulant(13,[3,5,7])
            Circulant graph ([3, 5, 7]): Digraph on 13 vertices

        TESTS::

            sage: digraphs.Circulant(13,[3,5,7,"hey"])
            Traceback (most recent call last):
            ...
            ValueError: The list must contain only relative integers.
            sage: digraphs.Circulant(-2,[3,5,7,3])
            Traceback (most recent call last):
            ...
            ValueError: n must be a positive integer
            sage: digraphs.Circulant(3,[3,5,7,3.4])
            Traceback (most recent call last):
            ...
            ValueError: The list must contain only relative integers.
        """
        from sage.graphs.graph_plot import _circle_embedding
        from sage.rings.integer_ring import ZZ

        # Bad input and loops
        loops = False
        if not n in ZZ or n <= 0:
            raise ValueError("n must be a positive integer")

        for i in integers:
            if not i in ZZ:
                raise ValueError(
                    "The list must contain only relative integers.")
            if (i % n) == 0:
                loops = True

        G = DiGraph(n,
                    name="Circulant graph (" + str(integers) + ")",
                    loops=loops)

        _circle_embedding(G, range(n))
        for v in range(n):
            G.add_edges([(v, (v + j) % n) for j in integers])

        return G
Ejemplo n.º 8
0
    def Circulant(self,n,integers):
        r"""
        Returns a circulant digraph on `n` vertices from a set of integers.

        INPUT:

        - ``n`` (integer) -- number of vertices.

        - ``integers`` -- the list of integers such that there is an edge from
          `i` to `j` if and only if ``(j-i)%n in integers``.

        EXAMPLE::

            sage: digraphs.Circulant(13,[3,5,7])
            Circulant graph ([3, 5, 7]): Digraph on 13 vertices

        TESTS::

            sage: digraphs.Circulant(13,[3,5,7,"hey"])
            Traceback (most recent call last):
            ...
            ValueError: The list must contain only relative integers.
            sage: digraphs.Circulant(-2,[3,5,7,3])
            Traceback (most recent call last):
            ...
            ValueError: n must be a positive integer
            sage: digraphs.Circulant(3,[3,5,7,3.4])
            Traceback (most recent call last):
            ...
            ValueError: The list must contain only relative integers.
        """
        from sage.graphs.graph_plot import _circle_embedding
        from sage.rings.integer_ring import ZZ

        # Bad input and loops
        loops = False
        if not n in ZZ or n <= 0:
            raise ValueError("n must be a positive integer")

        for i in integers:
            if not i in ZZ:
                raise ValueError("The list must contain only relative integers.")
            if (i%n) == 0:
                loops = True

        G=DiGraph(n, name="Circulant graph ("+str(integers)+")", loops=loops)

        _circle_embedding(G, range(n))
        for v in range(n):
            G.add_edges([(v,(v+j)%n) for j in integers])

        return G
Ejemplo n.º 9
0
def shard_preorder_graph(runs):
    """
    Return the preorder attached to a tuple of decreasing runs.

    This is a directed graph, whose vertices correspond to the runs.

    There is an edge from a run `R` to a run `S` if `R` is before `S`
    in the list of runs and the two intervals defined by the initial and
    final indices of `R` and `S` overlap.

    This only depends on the initial and final indices of the runs.
    For this reason, this input can also be given in that shorten way.

    INPUT:

    - a tuple of tuples, the runs of a permutation, or

    - a tuple of pairs `(i,j)`, each one standing for a run from `i` to `j`.

    OUTPUT:

    a directed graph, with vertices labelled by integers

    EXAMPLES::

        sage: from sage.combinat.shard_order import shard_preorder_graph
        sage: s = Permutation([2,8,3,9,6,4,5,1,7])
        sage: def cut(lr):
        ....:     return tuple((r[0], r[-1]) for r in lr)
        sage: shard_preorder_graph(cut(s.decreasing_runs()))
        Digraph on 5 vertices
        sage: s = Permutation([9,4,3,2,8,6,5,1,7])
        sage: P = shard_preorder_graph(s.decreasing_runs())
        sage: P.is_isomorphic(digraphs.TransitiveTournament(3))
        True
    """
    N = len(runs)
    dg = DiGraph(N)
    dg.add_edges((i, j) for i in range(N - 1)
                 for j in range(i + 1, N)
                 if runs[i][-1] < runs[j][0] and runs[j][-1] < runs[i][0])
    return dg
Ejemplo n.º 10
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
Ejemplo n.º 11
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