Example #1
0
def CircularLadderGraph(n):
    """
    Returns a circular ladder graph with 2\*n nodes.

    A Circular ladder graph is a ladder graph that is connected at the
    ends, i.e.: a ladder bent around so that top meets bottom. Thus it
    can be described as two parallel cycle graphs connected at each
    corresponding node pair.

    This constructor depends on NetworkX numeric labels.

    PLOTTING: Upon construction, the position dictionary is filled to
    override the spring-layout algorithm. By convention, the circular
    ladder graph is displayed as an inner and outer cycle pair, with
    the first n nodes drawn on the inner circle. The first (0) node is
    drawn at the top of the inner-circle, moving clockwise after that.
    The outer circle is drawn with the (n+1)th node at the top, then
    counterclockwise as well.

    EXAMPLES: Construct and show a circular ladder graph with 26 nodes

    ::

        sage: g = graphs.CircularLadderGraph(13)
        sage: g.show() # long time

    Create several circular ladder graphs in a Sage graphics array

    ::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.CircularLadderGraph(i+3)
        ....:    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
    """
    pos_dict = {}
    for i in range(n):
        x = float(cos((pi / 2) + ((2 * pi) / n) * i))
        y = float(sin((pi / 2) + ((2 * pi) / n) * i))
        pos_dict[i] = [x, y]
    for i in range(n, 2 * n):
        x = float(2 * (cos((pi / 2) + ((2 * pi) / n) * (i - n))))
        y = float(2 * (sin((pi / 2) + ((2 * pi) / n) * (i - n))))
        pos_dict[i] = (x, y)

    G = Graph(pos=pos_dict, name="Circular Ladder graph")
    G.add_vertices(range(2 * n))
    G.add_cycle(range(n))
    G.add_cycle(range(n, 2 * n))
    G.add_edges((i, i + n) for i in range(n))
    return G
Example #2
0
def CircularLadderGraph(n):
    """
    Returns a circular ladder graph with 2\*n nodes.

    A Circular ladder graph is a ladder graph that is connected at the
    ends, i.e.: a ladder bent around so that top meets bottom. Thus it
    can be described as two parallel cycle graphs connected at each
    corresponding node pair.

    This constructor depends on NetworkX numeric labels.

    PLOTTING: Upon construction, the position dictionary is filled to
    override the spring-layout algorithm. By convention, the circular
    ladder graph is displayed as an inner and outer cycle pair, with
    the first n nodes drawn on the inner circle. The first (0) node is
    drawn at the top of the inner-circle, moving clockwise after that.
    The outer circle is drawn with the (n+1)th node at the top, then
    counterclockwise as well.

    EXAMPLES: Construct and show a circular ladder graph with 26 nodes

    ::

        sage: g = graphs.CircularLadderGraph(13)
        sage: g.show() # long time

    Create several circular ladder graphs in a Sage graphics array

    ::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.CircularLadderGraph(i+3)
        ....:    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
    """
    pos_dict = {}
    for i in range(n):
        x = float(cos((pi/2) + ((2*pi)/n)*i))
        y = float(sin((pi/2) + ((2*pi)/n)*i))
        pos_dict[i] = [x,y]
    for i in range(n,2*n):
        x = float(2*(cos((pi/2) + ((2*pi)/n)*(i-n))))
        y = float(2*(sin((pi/2) + ((2*pi)/n)*(i-n))))
        pos_dict[i] = (x,y)

    G = Graph(pos=pos_dict, name="Circular Ladder graph")
    G.add_vertices( range(2*n) )
    G.add_cycle( range(n) )
    G.add_cycle( range(n,2*n) )
    G.add_edges( (i,i+n) for i in range(n) )
    return G
Example #3
0
def CircularLadderGraph(n):
    r"""
    Return a circular ladder graph with `2 * n` nodes.

    A Circular ladder graph is a ladder graph that is connected at the ends,
    i.e.: a ladder bent around so that top meets bottom. Thus it can be
    described as two parallel cycle graphs connected at each corresponding node
    pair.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, the circular ladder graph is
    displayed as an inner and outer cycle pair, with the first `n` nodes drawn
    on the inner circle. The first (0) node is drawn at the top of the
    inner-circle, moving clockwise after that. The outer circle is drawn with
    the `(n+1)`th node at the top, then counterclockwise as well.
    When `n == 2`, we rotate the outer circle by an angle of `\pi/8` to ensure
    that all edges are visible (otherwise the 4 vertices of the graph would be
    placed on a single line).

    EXAMPLES:

    Construct and show a circular ladder graph with 26 nodes::

        sage: g = graphs.CircularLadderGraph(13)
        sage: g.show() # long time

    Create several circular ladder graphs in a Sage graphics array::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.CircularLadderGraph(i+3)
        ....:    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
    """
    G = Graph(2 * n, name="Circular Ladder graph")
    G._circle_embedding(list(range(n)), radius=1, angle=pi/2)
    if n == 2:
        G._circle_embedding(list(range(4)), radius=1, angle=pi/2 + pi/8)
    else:
        G._circle_embedding(list(range(n, 2*n)), radius=2, angle=pi/2)
    G.add_cycle(list(range(n)))
    G.add_cycle(list(range(n, 2 * n)))
    G.add_edges((i, i + n) for i in range(n))
    return G
Example #4
0
def CircularLadderGraph(n):
    r"""
    Return a circular ladder graph with `2 * n` nodes.

    A Circular ladder graph is a ladder graph that is connected at the ends,
    i.e.: a ladder bent around so that top meets bottom. Thus it can be
    described as two parallel cycle graphs connected at each corresponding node
    pair.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, the circular ladder graph is
    displayed as an inner and outer cycle pair, with the first `n` nodes drawn
    on the inner circle. The first (0) node is drawn at the top of the
    inner-circle, moving clockwise after that. The outer circle is drawn with
    the `(n+1)`th node at the top, then counterclockwise as well.
    When `n == 2`, we rotate the outer circle by an angle of `\pi/8` to ensure
    that all edges are visible (otherwise the 4 vertices of the graph would be
    placed on a single line).

    EXAMPLES:

    Construct and show a circular ladder graph with 26 nodes::

        sage: g = graphs.CircularLadderGraph(13)
        sage: g.show() # long time

    Create several circular ladder graphs in a Sage graphics array::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:    k = graphs.CircularLadderGraph(i+3)
        ....:    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
    """
    G = Graph(2 * n, name="Circular Ladder graph")
    G._circle_embedding(list(range(n)), radius=1, angle=pi/2)
    if n == 2:
        G._circle_embedding(list(range(4)), radius=1, angle=pi/2 + pi/8)
    else:
        G._circle_embedding(list(range(n, 2*n)), radius=2, angle=pi/2)
    G.add_cycle(list(range(n)))
    G.add_cycle(list(range(n, 2 * n)))
    G.add_edges( (i,i+n) for i in range(n) )
    return G
Example #5
0
def CycleGraph(n):
    r"""
    Return a cycle graph with `n` nodes.

    A cycle graph is a basic structure which is also typically called an
    `n`-gon.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, each cycle graph will be
    displayed with the first (0) node at the top, with the rest following in a
    counterclockwise manner.

    The cycle graph is a good opportunity to compare efficiency of filling a
    position dictionary vs. using the spring-layout algorithm for
    plotting. Because the cycle graph is very symmetric, the resulting plots
    should be similar (in cases of small `n`).

    Filling the position dictionary in advance adds `O(n)` to the constructor.

    EXAMPLES:

    Compare plotting using the predefined layout and networkx::

        sage: import networkx
        sage: n = networkx.cycle_graph(23)
        sage: spring23 = Graph(n)
        sage: posdict23 = graphs.CycleGraph(23)
        sage: spring23.show()  # long time
        sage: posdict23.show()  # long time

    We next view many cycle graphs as a Sage graphics array. First we use the
    ``CycleGraph`` constructor, which fills in the position dictionary::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.CycleGraph(i+3)
        ....:     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

    Compare to plotting with the spring-layout algorithm::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.cycle_graph(i+3)
        ....:     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

    TESTS:

    The input parameter must be a positive integer::

        sage: G = graphs.CycleGraph(-1)
        Traceback (most recent call last):
        ...
        ValueError: parameter n must be a positive integer
    """
    if n < 0:
        raise ValueError("parameter n must be a positive integer")

    G = Graph(n, name="Cycle graph")
    if n == 1:
        G.set_pos({0: (0, 0)})
    else:
        G._circle_embedding(list(range(n)), angle=pi/2)
        G.add_cycle(list(range(n)))
    return G
Example #6
0
def CycleGraph(n):
    r"""
    Return a cycle graph with n nodes.

    A cycle graph is a basic structure which is also typically called an
    `n`-gon.

    PLOTTING: Upon construction, the position dictionary is filled to override
    the spring-layout algorithm. By convention, each cycle graph will be
    displayed with the first (0) node at the top, with the rest following in a
    counterclockwise manner.

    The cycle graph is a good opportunity to compare efficiency of filling a
    position dictionary vs. using the spring-layout algorithm for
    plotting. Because the cycle graph is very symmetric, the resulting plots
    should be similar (in cases of small `n`).

    Filling the position dictionary in advance adds `O(n)` to the constructor.

    EXAMPLES: Compare plotting using the predefined layout and networkx::

        sage: import networkx
        sage: n = networkx.cycle_graph(23)
        sage: spring23 = Graph(n)
        sage: posdict23 = graphs.CycleGraph(23)
        sage: spring23.show() # long time
        sage: posdict23.show() # long time

    We next view many cycle graphs as a Sage graphics array. First we use the
    ``CycleGraph`` constructor, which fills in the position dictionary::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.CycleGraph(i+3)
        ....:     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

    Compare to plotting with the spring-layout algorithm::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     spr = networkx.cycle_graph(i+3)
        ....:     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

    TESTS:

    The input parameter must be a positive integer::

        sage: G = graphs.CycleGraph(-1)
        Traceback (most recent call last):
        ...
        ValueError: parameter n must be a positive integer
    """
    if n < 0:
        raise ValueError("parameter n must be a positive integer")

    G = Graph(n, name="Cycle graph")
    if n == 1:
        G.set_pos({0:(0, 0)})
    else:
        G._circle_embedding(list(range(n)), angle=pi/2)
        G.add_cycle(list(range(n)))
    return G
def random_cycle_paths(max_cycle_len,
                       max_path_len,
                       max_vertices,
                       p=0,
                       min_cycle_len=1):
    '''Funkcja losująca grafy nieskierowane o dokładnie jedym cyklu, z którego
    wychodzą ścieżki dwóch typów. Pierwszym z nich jest typ "zewnętrzny", czyli
    ścieżki, które zaczynają się w jednym z wierzchołków cyklu i których
    pozostałe wierzchołki są z cyklem rozłączne. Drugi typ jest "wewnętrzny",
    do którego należą ścieżki o dwóch wierzchołkach końcowych należących do
    cyklu lub innej ścieżki wewnętrznej. Wszystkie ścieżki wewnętrzne są
    losowane tak, żeby graf był planarny pod warukiem, że rysowanie ścieżek
    wewnętrznych ograniczamy do wnętrza cyklu.

    :param min_cycle_len: Int
        Minimalna dozwolona długość cyklu.
    :param max_cycle_len: Int
        Największa dozwolona długość cyklu. Jeżeli długość wylosowanego cyklu
        będzie równa `1`, to wygenerowany zostanie wierzchołek, a jeżeli będzie
        równa `2`, to wygenerowana zostanie krawędź.
    :param max_path_len: Int
        Największa dozwolona długość ścieżki wychodzącej z cyklu.
    :param p: Float
        Określa, z jakim prawdopodobieństwem do grafu zostanie dodana kolejna
        ścieżka zewnętrzna. Z prawdopodobieństwem `1-p` zostanie dodana krawędź
        wewnętrzna.
    :param max_vertices: Int
        Największa dozwolona liczba krawędzi.
    :return: tuple
        Para składająca się z opisanego grafu skierowanego, oraz listy
        wierzchołków składającej się z wierzchołków cyklu oraz ścieżek
        "zewnętrznych".
    '''
    if p < 0 or p > 1:
        raise ValueError("Niepoprawna wartość prawdopodobieństwa. `p` musi "
                         "należeć do przedziału [0, 1]")
    if min_cycle_len < 1:
        raise ValueError("Minimalna długość cyklu nie może być mniejsza od 1.")
    if min_cycle_len > max_cycle_len:
        raise ValueError("Minimalna długość cyklu musi być mniejsza lub równa "
                         "maksymalnej.")
    if min_cycle_len < 3 and p < 1:
        warnings.warn("Minimalna długość cyklu pozwala na stworzenie cykli "
                      "bez wnętrza, a wartość `p` dopuszcza istnienie ścieżek "
                      "wewnętrznych. W przypadku wylosowania krótkiego cyklu, "
                      "wszystkie ścieżki będą zewnętrzne.")
    G = Graph()
    cycle_len = np.random.randint(min_cycle_len, max_cycle_len + 1)
    if cycle_len == 1:
        p = 1
        G.add_vertex(0)
        outside_vertices = [0]
    elif cycle_len == 2:
        p = 1
        G.add_edge((0, 1))
        outside_vertices = [0, 1]
    else:
        G.add_cycle(list(range(0, cycle_len)))
        outside_vertices = list(range(0, cycle_len))
    n = cycle_len
    got_max_vertices = n >= max_vertices
    cycle_partitions = [list(range(0, n))]
    for i in range(cycle_len):
        if got_max_vertices:
            break
        n_paths = np.random.poisson(1)
        path_lengths = np.random.poisson(lam=int(max_path_len / 2),
                                         size=n_paths)
        for path_length in path_lengths:
            if n + path_length > max_vertices:
                path_length = max_vertices - n
                got_max_vertices = True
            if path_length == 0:
                if got_max_vertices:
                    break
                else:
                    continue
            if np.random.rand(1) > p:
                available_parts = [tab for tab in cycle_partitions if i in tab]
                cycle_part = \
                    available_parts[np.random.randint(0, len(available_parts))]
                j = i
                while j == i:
                    j = np.random.choice(cycle_part)
                # split
                k = 0
                parts = [[], []]
                part_id = 0
                new_path = list(range(n, n + path_length - 1))
                for k in cycle_part:
                    parts[part_id].append(k)
                    if k in [i, j]:
                        if k == i:
                            parts[part_id] += new_path
                        else:
                            parts[part_id] += new_path[::-1]
                        part_id = 1 - part_id
                        parts[part_id].append(k)
                cycle_partitions.remove(cycle_part)
                cycle_partitions.append(parts[0])
                cycle_partitions.append(parts[1])
                G.add_path([i] + new_path + [j])
            else:
                G.add_path([i] + list(range(n, n + path_length)))
                outside_vertices += list(range(n, n + path_length))
            n += path_length
            if got_max_vertices:
                break
    return G, outside_vertices