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
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
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
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
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
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