Пример #1
0
def LadderGraph(n):
    """
    Returns a ladder graph with 2\*n nodes.

    A ladder graph is a basic structure that is typically displayed as
    a ladder, i.e.: two parallel path 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, each ladder
    graph will be displayed horizontally, with the first n nodes
    displayed left to right on the top horizontal line.

    EXAMPLES: Construct and show a ladder graph with 14 nodes

    ::

        sage: g = graphs.LadderGraph(7)
        sage: g.show() # long time

    Create several ladder graphs in a Sage graphics array

    ::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.LadderGraph(i+2)
        ....:     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):
        pos_dict[i] = (i,1)
    for i in range(n,2*n):
        x = i - n
        pos_dict[i] = (x,0)
    G = Graph(pos=pos_dict, name="Ladder graph")
    G.add_vertices( range(2*n) )
    G.add_path( range(n) )
    G.add_path( range(n,2*n) )
    G.add_edges( (i,i+n) for i in range(n) )
    return G
Пример #2
0
def LadderGraph(n):
    """
    Returns a ladder graph with 2\*n nodes.

    A ladder graph is a basic structure that is typically displayed as
    a ladder, i.e.: two parallel path 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, each ladder
    graph will be displayed horizontally, with the first n nodes
    displayed left to right on the top horizontal line.

    EXAMPLES: Construct and show a ladder graph with 14 nodes

    ::

        sage: g = graphs.LadderGraph(7)
        sage: g.show() # long time

    Create several ladder graphs in a Sage graphics array

    ::

        sage: g = []
        sage: j = []
        sage: for i in range(9):
        ....:     k = graphs.LadderGraph(i+2)
        ....:     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):
        pos_dict[i] = (i, 1)
    for i in range(n, 2 * n):
        x = i - n
        pos_dict[i] = (x, 0)
    G = Graph(pos=pos_dict, name="Ladder graph")
    G.add_vertices(range(2 * n))
    G.add_path(range(n))
    G.add_path(range(n, 2 * n))
    G.add_edges((i, i + n) for i in 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