Example #1
0
def CompleteBipartiteGraph(p, q, set_position=True):
    r"""
    Return a Complete Bipartite Graph on `p + q` vertices.

    A Complete Bipartite Graph is a graph with its vertices partitioned into two
    groups, `V_1 = \{0,...,p-1\}` and `V_2 = \{p,...,p+q-1\}`. Each `u \in
    V_1` is connected to every `v \in V_2`.

    INPUT:

    - ``p,q`` -- number of vertices in each side

    - ``set_position`` -- boolean (default ``True``); if set to ``True``, we
      assign positions to the vertices so that the set of cardinality `p` is
      on the line `y=1` and the set of cardinality `q` is on the line `y=0`.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, each complete bipartite graph
    will be displayed with the first `p` nodes on the top row (at `y=1`) from
    left to right. The remaining `q` nodes appear at `y=0`, also from left to
    right. The shorter row (partition with fewer nodes) is stretched to the same
    length as the longer row, unless the shorter row has 1 node; in which case
    it is centered. The `x` values in the plot are in domain `[0, \max(p, q)]`.

    In the Complete Bipartite graph, there is a visual difference in using the
    spring-layout algorithm vs. the position dictionary used in this
    constructor. The position dictionary flattens the graph and separates the
    partitioned nodes, making it clear which nodes an edge is connected to. The
    Complete Bipartite graph plotted with the spring-layout algorithm tends to
    center the nodes in `p` (see ``spring_med`` in examples below), thus
    overlapping its nodes and edges, making it typically hard to decipher.

    Filling the position dictionary in advance adds `O(n)` to the constructor.
    Feel free to race the constructors below in the examples section. The much
    larger difference is the time added by the spring-layout algorithm when
    plotting. (Also shown in the example below). The spring model is typically
    described as `O(n^3)`, as appears to be the case in the NetworkX source
    code.

    EXAMPLES:

    Two ways of constructing the complete bipartite graph, using different
    layout algorithms::

        sage: import networkx
        sage: n = networkx.complete_bipartite_graph(389, 157); spring_big = Graph(n)   # long time
        sage: posdict_big = graphs.CompleteBipartiteGraph(389, 157)                    # long time

    Compare the plotting::

        sage: n = networkx.complete_bipartite_graph(11, 17)
        sage: spring_med = Graph(n)
        sage: posdict_med = graphs.CompleteBipartiteGraph(11, 17)

    Notice here how the spring-layout tends to center the nodes of `n1`::

        sage: spring_med.show()  # long time
        sage: posdict_med.show()  # long time

    View many complete bipartite graphs with a Sage Graphics Array, with this
    constructor (i.e., the position dictionary filled)::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.CompleteBipartiteGraph(i+1,4)
        ....:     g.append(k)
        sage: for i in range(3):
        ....:     n = []
        ....:     for m in range(3):
        ....:         n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
        ....:     j.append(n)
        sage: G = graphics_array(j)
        sage: G.show()  # long time

    We compare to plotting with the spring-layout algorithm::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.complete_bipartite_graph(i+1,4)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        sage: for i in range(3):
        ....:     n = []
        ....:     for m in range(3):
        ....:         n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
        ....:     j.append(n)
        sage: G = graphics_array(j)
        sage: G.show()  # long time

    :trac:`12155`::

        sage: graphs.CompleteBipartiteGraph(5,6).complement()
        complement(Complete bipartite graph of order 5+6): Graph on 11 vertices

    TESTS:

    Prevent negative dimensions (:trac:`18530`)::

        sage: graphs.CompleteBipartiteGraph(-1,1)
        Traceback (most recent call last):
        ...
        ValueError: the arguments p(=-1) and q(=1) must be positive integers
        sage: graphs.CompleteBipartiteGraph(1,-1)
        Traceback (most recent call last):
        ...
        ValueError: the arguments p(=1) and q(=-1) must be positive integers
    """
    if p < 0 or q < 0:
        raise ValueError('the arguments p(={}) and q(={}) must be positive integers'.format(p, q))

    G = Graph(p + q, name="Complete bipartite graph of order {}+{}".format(p, q))
    G.add_edges((i, j) for i in range(p) for j in range(p, p + q))

    # We now assign positions to vertices:
    # - vertices 0,..,p-1 are placed on the line (0, 1) to (max(p, q), 1)
    # - vertices p,..,p+q-1 are placed on the line (0, 0) to (max(p, q), 0)
    # If p (or q) is 1, the vertex is centered in the line.
    if set_position:
        nmax = max(p, q)
        G._line_embedding(list(range(p)), first=(0, 1), last=(nmax, 1))
        G._line_embedding(list(range(p, p + q)), first=(0, 0), last=(nmax, 0))

    return G
Example #2
0
def CompleteMultipartiteGraph(l):
    r"""
    Return a complete multipartite graph.

    INPUT:

    - ``l`` -- a list of integers; the respective sizes of the components

    PLOTTING: Produce a layout of the vertices so that vertices in the same
    vertex set are adjacent and clearly separated from vertices in other vertex
    sets.

    This is done by calculating the vertices of an `r`-gon then calculating the
    slope between adjacent vertices. We then 'walk' around the `r`-gon placing
    graph vertices in regular intervals between adjacent vertices of the
    `r`-gon.

    Makes a nicely organized graph like in this picture:
    https://commons.wikimedia.org/wiki/File:Turan_13-4.svg

    EXAMPLES:

    A complete tripartite graph with sets of sizes `5, 6, 8`::

        sage: g = graphs.CompleteMultipartiteGraph([5, 6, 8]); g
        Multipartite Graph with set sizes [5, 6, 8]: Graph on 19 vertices

    It clearly has a chromatic number of 3::

        sage: g.chromatic_number()
        3
    """
    r = len(l)  # getting the number of partitions
    name = "Multipartite Graph with set sizes {}".format(l)

    if not r:
        g = Graph()
    elif r == 1:
        g = Graph(l[0])
        g._line_embedding(range(l[0]), first=(0, 0), last=(l[0], 0))
    elif r == 2:
        g = CompleteBipartiteGraph(l[0], l[1])
        g.name(name)
    else:
        # This position code gives bad results on bipartite or isolated graphs
        points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)]
        slopes = [(points[(i + 1) % r][0] - points[i % r][0],
                   points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)]

        counter = 0
        positions = {}
        for i in range(r):
            vertex_set_size = l[i] + 1
            for j in range(1, vertex_set_size):
                x = points[i][0] + slopes[i][0] * j / vertex_set_size
                y = points[i][1] + slopes[i][1] * j / vertex_set_size
                positions[counter] = (x, y)
                counter += 1

        g = Graph(sum(l))
        s = 0
        for i in l:
            g.add_clique(range(s, s + i))
            s += i

        g = g.complement()
        g.set_pos(positions)

    g.name(name)
    return g
Example #3
0
def CompleteBipartiteGraph(n1, n2, set_position=True):
    r"""
    Return a Complete Bipartite Graph on `n1 + n2` vertices.

    A Complete Bipartite Graph is a graph with its vertices partitioned into two
    groups, `V_1 = \{0,...,n1-1\}` and `V_2 = \{n1,...,n1+n2-1\}`. Each `u \in
    V_1` is connected to every `v \in V_2`.

    INPUT:

    - ``n1, n2`` -- number of vertices in each side

    - ``set_position`` -- boolean (default ``True``); if set to ``True``, we
      assign positions to the vertices so that the set of cardinality `n1` is
      on the line `y=1` and the set of cardinality `n2` is on the line `y=0`.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, each complete bipartite graph
    will be displayed with the first `n1` nodes on the top row (at `y=1`) from
    left to right. The remaining `n2` nodes appear at `y=0`, also from left to
    right. The shorter row (partition with fewer nodes) is stretched to the same
    length as the longer row, unless the shorter row has 1 node; in which case
    it is centered. The `x` values in the plot are in domain `[0, \max(n1,
    n2)]`.

    In the Complete Bipartite graph, there is a visual difference in using the
    spring-layout algorithm vs. the position dictionary used in this
    constructor. The position dictionary flattens the graph and separates the
    partitioned nodes, making it clear which nodes an edge is connected to. The
    Complete Bipartite graph plotted with the spring-layout algorithm tends to
    center the nodes in n1 (see spring_med in examples below), thus overlapping
    its nodes and edges, making it typically hard to decipher.

    Filling the position dictionary in advance adds `O(n)` to the constructor.
    Feel free to race the constructors below in the examples section. The much
    larger difference is the time added by the spring-layout algorithm when
    plotting. (Also shown in the example below). The spring model is typically
    described as `O(n^3)`, as appears to be the case in the NetworkX source
    code.

    EXAMPLES:

    Two ways of constructing the complete bipartite graph, using different
    layout algorithms::

        sage: import networkx
        sage: n = networkx.complete_bipartite_graph(389, 157); spring_big = Graph(n)   # long time
        sage: posdict_big = graphs.CompleteBipartiteGraph(389, 157)                    # long time

    Compare the plotting::

        sage: n = networkx.complete_bipartite_graph(11, 17)
        sage: spring_med = Graph(n)
        sage: posdict_med = graphs.CompleteBipartiteGraph(11, 17)

    Notice here how the spring-layout tends to center the nodes of `n1`::

        sage: spring_med.show() # long time
        sage: posdict_med.show() # long time

    View many complete bipartite graphs with a Sage Graphics Array, with this
    constructor (i.e., the position dictionary filled)::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.CompleteBipartiteGraph(i+1,4)
        ....:     g.append(k)
        sage: for i in range(3):
        ....:     n = []
        ....:     for m in range(3):
        ....:         n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
        ....:     j.append(n)
        sage: G = sage.plot.graphics.GraphicsArray(j)
        sage: G.show() # long time

    We compare to plotting with the spring-layout algorithm::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.complete_bipartite_graph(i+1,4)
        ....:     k = Graph(spr)
        ....:     g.append(k)
        sage: for i in range(3):
        ....:     n = []
        ....:     for m in range(3):
        ....:         n.append(g[3*i + m].plot(vertex_size=50, vertex_labels=False))
        ....:     j.append(n)
        sage: G = sage.plot.graphics.GraphicsArray(j)
        sage: G.show() # long time

    :trac:`12155`::

        sage: graphs.CompleteBipartiteGraph(5,6).complement()
        complement(Complete bipartite graph of order 5+6): Graph on 11 vertices

    TESTS:

    Prevent negative dimensions (:trac:`18530`)::

        sage: graphs.CompleteBipartiteGraph(-1,1)
        Traceback (most recent call last):
        ...
        ValueError: the arguments n1(=-1) and n2(=1) must be positive integers
        sage: graphs.CompleteBipartiteGraph(1,-1)
        Traceback (most recent call last):
        ...
        ValueError: the arguments n1(=1) and n2(=-1) must be positive integers
    """
    if n1<0 or n2<0:
        raise ValueError('the arguments n1(={}) and n2(={}) must be positive integers'.format(n1,n2))

    G = Graph(n1+n2, name="Complete bipartite graph of order {}+{}".format(n1, n2))
    G.add_edges((i,j) for i in range(n1) for j in range(n1,n1+n2))

    # We now assign positions to vertices:
    # - vertices 0,..,n1-1 are placed on the line (0, 1) to (max(n1, n2), 1)
    # - vertices n1,..,n1+n2-1 are placed on the line (0, 0) to (max(n1, n2), 0)
    # If n1 (or n2) is 1, the vertex is centered in the line.
    if set_position:
        nmax = max(n1, n2)
        G._line_embedding(list(range(n1)), first=(0, 1), last=(nmax, 1))
        G._line_embedding(list(range(n1, n1+n2)), first=(0, 0), last=(nmax, 0))

    return G