def test_component_list(self): g = SimpleGraph() g.from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) comps = g.component_list() assert [1, 2, 3, 4, 5] in comps.values() assert [6, 7] in comps.values()
def find_shortest_path_dijkstra( g: SimpleGraph, source: Node) -> Tuple[Dict[int, float], Dict[int, int]]: """ Przyjmuje graf i zrodlo (wierzcholek). Zwraca: - slownik odleglosci od zrodla - slownik poprzednikow """ predecessors = {} distance = {} # kolejka priorytetowa dla wierzchołkow grafu (klucz: aktualnie wyliczona odleglosc) Q = [] for node in g.nodes: distance[node] = float("inf") predecessors[node] = None Q.append(node) distance[source] = 0 while Q: Q.sort(key=lambda n: distance[n]) u = Q.pop(0) for v in g.node_neighbours(u): if v in Q: new_distance = distance[u] + g.edge_to_node(u, v).weight old_distance = distance[v] if new_distance < old_distance: distance[v] = new_distance predecessors[v] = u d = {node: distance[node] for node in g.nodes} p = {node: predecessors[node] for node in g.nodes} return d, p
def test_components(self): g = SimpleGraph() g.from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) comps = g.components() assert comps[1] == comps[2] == comps[3] == comps[4] == comps[5] assert comps[6] == comps[7] assert comps[1] != comps[6]
def example05(): g = SimpleGraph().from_coordinates("input.dat") P = None for MAX_IT in range(10, 150, 5): P = simulated_annealing(g, MAX_IT, save=True, P=P) length = circuit_length(g.to_adjacency_matrix(), P) with open("P_5.tmp", "a") as f: f.write(f"{length:.3f}, {P}\n")
def example01(): """Ciąg graficzny""" print(is_valid_graph_sequence([4, 3, 3, 2, 2, 1, 1])) print(is_valid_graph_sequence([4, 3, 3, 2, 2, 1])) print(is_valid_graph_sequence([4, 4, 3, 1, 2])) g = SimpleGraph().from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) g.save(filename="graph1", file_format="png")
def example07(): g = SimpleGraph().from_coordinates("input.dat") P = None for _ in range(100): P = simulated_annealing(g, MAX_IT=100, save=True, P=P) length = circuit_length(g.to_adjacency_matrix(), P) print(length) with open("P.dat", "a") as f: f.write(f"{length:.3f}, {P}\n")
def test_save_to_file_and_load(self): g = SimpleGraph(8) g.add_random_edges(15) before = g.to_adjacency_list() g.save("test", "al") g.load("test.al") after = g.to_adjacency_list() assert before == after
def test_incidence_matrix_file(self): g = SimpleGraph(8) g.add_random_edges(15) before = g.to_adjacency_matrix() g.save("test", "im") g.load("test.im") after = g.to_adjacency_matrix() assert before == after
def get_k_regular_graph(size, k, connected=False) -> SimpleGraph: """Graf z wierzchołkami o tym samym stopniu""" seq = [k for _ in range(size)] g = SimpleGraph().from_graph_sequence(seq) if connected: if k < 2 and size != 2: raise ValueError("Nie da się stworzyć zadanego grafu.") while True: if g.is_connected_graph(): break g.randomize(size) return g
def test_incidence_matrix(self): g = SimpleGraph(8) g.add_random_edges(15) before = g.to_adjacency_list() g.from_incidence_matrix(g.to_incidence_matrix()) after = g.to_adjacency_list() assert before == after
def load_graph_to_work_on(args): g = SimpleGraph() if args.load: g.load(args.load) elif args.n: g.add_nodes(int(args.n)) if args.l: g.add_random_edges(int(args.l)) elif args.p: g.connect_random(float(args.p)) return g
def simulated_annealing(g: SimpleGraph, MAX_IT=None, P: List[int] = None, save=False): if not g.is_complete(): return ValueError("Do tego algorytmu graf musi być pełny.") if P is None: P = [n for n in range(1, len(g) + 1)] random.shuffle(P) if MAX_IT is None: MAX_IT = len(g) adj_m = g.to_adjacency_matrix() d = circuit_length(adj_m, P) for i in range(100, 0, -1): T = 0.001 * i**2 for _ in range(MAX_IT): # switch: a-b c-d --> a-c b-d _, b, c, _ = _choose_nodes(P) P[b], P[c] = P[c], P[b] d_new = circuit_length(adj_m, P) if d_new < d: d = d_new else: r = random.random() if r < math.exp(-(d_new - d) / T): d = d_new else: # switch back P[b], P[c] = P[c], P[b] if save: x = [g.x[n - 1] for n in P] y = [g.y[n - 1] for n in P] # connect first and last point x.append(g.x[P[0] - 1]) y.append(g.y[P[0] - 1]) plt.plot(x, y, "-o") plt.title(f"MAX_IT={MAX_IT}, d={d:.3f}") plt.xlabel("x") plt.ylabel("y") plt.savefig("SA.png") plt.clf() return P
def test_is_connected_graph(self): g = SimpleGraph(4) g.connect(1, 2) g.connect(3, 4) assert not g.is_connected_graph() g.connect(2, 3) assert g.is_connected_graph()
def test_add_random_edges(self): g = SimpleGraph(8) # 8 vertices => max 28 edges g.add_random_edges(8) assert len(g.edges) == 8 g.add_random_edges(20) assert len(g.edges) == 28 with pytest.raises(ValueError): g.add_random_edges(1)
def test_adjacency_matrix(self): g = SimpleGraph(8) g.add_random_edges(15) before = g.to_adjacency_matrix() g.from_adjacency_matrix(before) after = g.to_adjacency_matrix() assert before == after
def find_hamiltonian_circuit(g: SimpleGraph) -> List[Node]: """Znajduje losowy cykl Hamiltona w grafie""" g = copy.deepcopy(g) if not g.is_connected_graph(): raise ValueError(f"Graf nie jest spójny:\n{g}") stack = [random.choice(tuple(g.nodes))] solution = hamilton_search_r(g, stack) return solution
def hamilton_search_r(g: SimpleGraph, stack: List[Node]) -> List[Node]: # Zawiera wszystkie wierzcholki if set(stack) == g.nodes: # Istnieje połączenie między pierwszym a ostatnim if g.is_connected(stack[0], stack[-1]): return stack else: stack.pop return [] else: for neighbour in g.node_neighbours(stack[-1]): if neighbour in stack: continue stack.append(neighbour) if hamilton_search_r(g, stack): return stack raise ValueError(f"Graf nie jest Hamiltonowski:\n{g}")
def get_eulerian_graph(size: int = None) -> SimpleGraph: """Losowy graf Eulerowski""" if size is None: size = random.randint(2, 16) while True: seq = [] for d in range(size): d = random.randint(2, size - 1) seq.append(d - d % 2) if is_valid_graph_sequence(seq): break g = SimpleGraph().from_graph_sequence(seq) while True: if g.is_connected_graph(): break g.randomize(size) return g
def find_eulerian_trail(g: SimpleGraph) -> List[Node]: """Znajduje losowy cykl Eulera w grafie""" if not g.is_eulerian(): raise ValueError(f"Nie jest to graf Eulerowski\n{g}") solution = [] stack = [random.choice(tuple(g.nodes))] while len(stack) != 0: current_vertex = stack[-1] if g.node_degree(current_vertex) == 0: solution.append(current_vertex) stack.pop() else: next_vertex = random.choice(tuple( g.node_edges(current_vertex))).end g.disconnect(current_vertex, next_vertex) stack.append(next_vertex) return solution
def test_connect(self): g = SimpleGraph(8) n1 = 1 n2 = 2 g.connect(n1, n2) assert g.is_connected(n1, n2) assert g.is_connected(n2, n1) g.disconnect(n1, n2) assert not g.is_connected(n1, n2) assert not g.is_connected(n2, n1)
def get_minimum_spanning_tree_kruskal(g: SimpleGraph) -> SimpleGraph: """ Przyjmuje graf Zwraca jego minimalne drzewo rozpinające Korzysta z algorytmu kruskala """ # minimum spanning tree mst = SimpleGraph(len(g)) Q = [] for edge in g.edges: Q.append(edge) while Q and not mst.is_connected_graph(): Q.sort(key=lambda e: e.weight) current_edge = Q.pop(0) comps = mst.components() if comps[current_edge.begin] != comps[current_edge.end]: mst.edges.add(current_edge) return mst
def get_random_2D_graph( size=20, x_min=-50, x_max=50, y_min=-50, y_max=50 ) -> SimpleGraph: filename = f"{size}_coordinates.tmp" with open(filename, "w") as f: for _ in range(size): x = random.randint(x_min, x_max) y = random.randint(y_min, y_max) f.write(f"{x} {y}\n") g = SimpleGraph().from_coordinates(filename) return g
def test_from_graph_sequence(self): g = SimpleGraph() g.from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) assert g.to_adjacency_list() == { 1: {2, 3, 4, 5}, 2: {1, 3, 4}, 3: {1, 2, 5}, 4: {1, 2}, 5: {1, 3}, 6: {7}, 7: {6}, } assert g.graph_sequence() == [4, 3, 3, 2, 2, 1, 1] with pytest.raises(ValueError): g.from_graph_sequence([4, 3, 3, 2, 2, 1])
def example03(): """Największa wspólna składowa""" g = SimpleGraph().from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) g.save(filename="graph3", file_format="png", color_components=True) pprint(g.component_list()) print(f"Największa składowa: {g.largest_component()}")
def example02(): """Randomizacja""" g = SimpleGraph().from_graph_sequence([4, 3, 3, 2, 2, 1, 1]) g.save(filename="graph2_before", file_format="png") g.randomize(100) g.save(filename="graph2_after", file_format="png")
def test_breadth_first_search(self, graph, source, target, trail): g = SimpleGraph().from_adjacency_list(graph) tr = get_trail_to_node(breadth_first_search(g, source, target), target) assert tr == trail
def test_minimax_get_graph_center(self, graph, minimax_center): g = SimpleGraph().from_adjacency_matrix(graph) assert get_minimax_graph_center(g) == minimax_center
def get_random_graph(max_size=20) -> SimpleGraph: size = random.randint(2, max_size) g = SimpleGraph(size) g.connect_random(random.random()) return g
def load_graph_to_work_on(args): g = SimpleGraph() if args.load: g.load(args.load) elif args.n: g.add_nodes(int(args.n)) if args.l: g.add_random_edges(int(args.l)) elif args.p: g.connect_random(float(args.p)) if args.w is not None: if args.w[0]: g.assign_random_weights(int(args.w[0][0]), int(args.w[0][1])) else: g.assign_random_weights() return g