def test_nodelist(self): """Conversion from graph to sparse matrix to graph with nodelist.""" P4 = path_graph(4) P3 = path_graph(3) nodelist = list(P3.nodes()) A = nx.to_scipy_sparse_matrix(P4, nodelist=nodelist) GA = nx.Graph(A) assert nx.is_isomorphic(GA, P3) pytest.raises(nx.NetworkXError, nx.to_scipy_sparse_matrix, P3, nodelist=[]) # Test nodelist duplicates. long_nl = nodelist + [0] pytest.raises(nx.NetworkXError, nx.to_scipy_sparse_matrix, P3, nodelist=long_nl) # Test nodelist contains non-nodes non_nl = [-1, 0, 1, 2] pytest.raises(nx.NetworkXError, nx.to_scipy_sparse_matrix, P3, nodelist=non_nl)
def test_graph_edit_distance_edge_cost(self): G1 = path_graph(6) G2 = path_graph(6) for e, attr in G1.edges.items(): attr['color'] = 'red' if min(e) % 2 == 0 else 'blue' for e, attr in G2.edges.items(): attr['color'] = 'red' if min(e) // 3 == 0 else 'blue' def edge_subst_cost(gattr, hattr): if gattr['color'] == hattr['color']: return 0.01 else: return 0.1 def edge_del_cost(attr): if attr['color'] == 'blue': return 0.2 else: return 0.5 def edge_ins_cost(attr): if attr['color'] == 'blue': return 0.4 else: return 1.0 assert graph_edit_distance(G1, G2, edge_subst_cost=edge_subst_cost, edge_del_cost=edge_del_cost, edge_ins_cost=edge_ins_cost) == 0.23
def test_graph_edit_distance_edge_cost(self): G1 = path_graph(6) G2 = path_graph(6) for e, attr in G1.edges.items(): attr["color"] = "red" if min(e) % 2 == 0 else "blue" for e, attr in G2.edges.items(): attr["color"] = "red" if min(e) // 3 == 0 else "blue" def edge_subst_cost(gattr, hattr): if gattr["color"] == hattr["color"]: return 0.01 else: return 0.1 def edge_del_cost(attr): if attr["color"] == "blue": return 0.2 else: return 0.5 def edge_ins_cost(attr): if attr["color"] == "blue": return 0.4 else: return 1.0 assert (graph_edit_distance( G1, G2, edge_subst_cost=edge_subst_cost, edge_del_cost=edge_del_cost, edge_ins_cost=edge_ins_cost, ) == 0.23)
def test_graph_edit_distance_node_cost(self): G1 = path_graph(6) G2 = path_graph(6) for n, attr in G1.nodes.items(): attr['color'] = 'red' if n % 2 == 0 else 'blue' for n, attr in G2.nodes.items(): attr['color'] = 'red' if n % 2 == 1 else 'blue' def node_subst_cost(uattr, vattr): if uattr['color'] == vattr['color']: return 1 else: return 10 def node_del_cost(attr): if attr['color'] == 'blue': return 20 else: return 50 def node_ins_cost(attr): if attr['color'] == 'blue': return 40 else: return 100 assert graph_edit_distance(G1, G2, node_subst_cost=node_subst_cost, node_del_cost=node_del_cost, node_ins_cost=node_ins_cost) == 6
def test_graph_edit_distance_node_cost(self): G1 = path_graph(6) G2 = path_graph(6) for n, attr in G1.nodes.items(): attr["color"] = "red" if n % 2 == 0 else "blue" for n, attr in G2.nodes.items(): attr["color"] = "red" if n % 2 == 1 else "blue" def node_subst_cost(uattr, vattr): if uattr["color"] == vattr["color"]: return 1 else: return 10 def node_del_cost(attr): if attr["color"] == "blue": return 20 else: return 50 def node_ins_cost(attr): if attr["color"] == "blue": return 40 else: return 100 assert (graph_edit_distance( G1, G2, node_subst_cost=node_subst_cost, node_del_cost=node_del_cost, node_ins_cost=node_ins_cost, ) == 6)
def test_graph_edit_distance_edge_match(self): G1 = path_graph(6) G2 = path_graph(6) for e, attr in G1.edges.items(): attr['color'] = 'red' if min(e) % 2 == 0 else 'blue' for e, attr in G2.edges.items(): attr['color'] = 'red' if min(e) // 3 == 0 else 'blue' assert graph_edit_distance(G1, G2) == 0 assert graph_edit_distance(G1, G2, edge_match=lambda e1, e2: e1['color'] == e2['color']) == 2
def test_graph_edit_distance_edge_match(self): G1 = path_graph(6) G2 = path_graph(6) for e, attr in G1.edges.items(): attr["color"] = "red" if min(e) % 2 == 0 else "blue" for e, attr in G2.edges.items(): attr["color"] = "red" if min(e) // 3 == 0 else "blue" assert graph_edit_distance(G1, G2) == 0 assert (graph_edit_distance( G1, G2, edge_match=lambda e1, e2: e1["color"] == e2["color"]) == 2)
def test_nodelist(self): """Conversion from graph to matrix to graph with nodelist.""" P4 = path_graph(4) P3 = path_graph(3) nodelist = P3.nodes() A = nx.to_numpy_matrix(P4, nodelist=nodelist) GA = nx.Graph(A) self.assert_equal(GA, P3) # Make nodelist ambiguous by containing duplicates. nodelist += [nodelist[0]] assert_raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nodelist)
def test_nodelist(self): """Conversion from graph to sparse matrix to graph with nodelist.""" P4 = path_graph(4) P3 = path_graph(3) nodelist = list(P3.nodes()) A = nx.to_scipy_sparse_matrix(P4, nodelist=nodelist) GA = nx.Graph(A) self.assert_isomorphic(GA, P3) # Make nodelist ambiguous by containing duplicates. nodelist += [nodelist[0]] pytest.raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nodelist)
def random_lobster(n, p1, p2, seed=None): """Returns a random lobster graph. A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes; setting ``p2`` to zero produces a caterillar. Parameters ---------- n : int The expected number of nodes in the backbone p1 : float Probability of adding an edge to the backbone p2 : float Probability of adding an edge one level beyond backbone seed : int, optional Seed for random number generator (default=None). """ # a necessary ingredient in any self-respecting graph library if seed is not None: random.seed(seed) llen = int(2 * random.random() * n + 0.5) L = path_graph(llen) L.name = "random_lobster(%d,%s,%s)" % (n, p1, p2) # build caterpillar: add edges to path graph with probability p1 current_node = llen - 1 for n in range(llen): if random.random() < p1: # add fuzzy caterpillar parts current_node += 1 L.add_edge(n, current_node) if random.random() < p2: # add crunchy lobster bits current_node += 1 L.add_edge(current_node - 1, current_node) return L # voila, un lobster!
def truncated_tetrahedron_graph(create_using=None): """ Returns the skeleton of the truncated Platonic tetrahedron. The truncated tetrahedron is an Archimedean solid with 4 regular hexagonal faces, 4 equilateral triangle faces, 12 nodes and 18 edges. It can be constructed by truncating all 4 vertices of a regular tetrahedron at one third of the original edge length [1]_. Parameters ---------- create_using : NetworkX graph constructor, optional (default=nx.Graph) Graph type to create. If graph instance, then cleared before populated. Returns ------- G : networkx Graph Skeleton of the truncated tetrahedron References ---------- .. [1] https://en.wikipedia.org/wiki/Truncated_tetrahedron """ G = path_graph(12, create_using) G.add_edges_from([(0, 2), (0, 9), (1, 6), (3, 11), (4, 11), (5, 7), (8, 10)]) G.name = "Truncated Tetrahedron Graph" return G
def random_lobster(n, p1, p2, seed=None): """Return a random lobster. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes (p2=0). A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. :Parameters: - `n`: the expected number of nodes in the backbone - `p1`: probability of adding an edge to the backbone - `p2`: probability of adding an edge one level beyond backbone - `seed`: seed for random number generator (default=None) """ # a necessary ingredient in any self-respecting graph library if seed is not None: random.seed(seed) llen=int(2*random.random()*n + 0.5) L=path_graph(llen) L.name="random_lobster(%d,%s,%s)"%(n,p1,p2) # build caterpillar: add edges to path graph with probability p1 current_node=llen-1 for n in xrange(llen): if random.random()<p1: # add fuzzy caterpillar parts current_node+=1 L.add_edge(n,current_node) if random.random()<p2: # add crunchy lobster bits current_node+=1 L.add_edge(current_node-1,current_node) return L # voila, un lobster!
def test_correctness(): # note: in the future can restrict all graphs to have the same number of nodes, for analysis graphs = [lambda: basic_graph(), lambda: complete_graph(10), lambda: balanced_tree(3, 5), lambda: barbell_graph(6, 7), lambda: binomial_tree(10), lambda: cycle_graph(50), lambda: path_graph(200), lambda: star_graph(200)] names = ["basic_graph", "complete_graph", "balanced_tree", "barbell_graph", "binomial_tree", "cycle_graph", "path_graph", "star_graph"] for graph, name in zip(graphs, names): print(f"Testing graph {name}...") # Initialize both graphs G_dinitz = graph() G_gr = graph() # Set random capacities of graph edges for u, v in G_dinitz.edges: cap = randint(1, 20) G_dinitz.edges[u, v]["capacity"] = cap G_gr.edges[u, v]["capacity"] = cap # Pick random start and end node start_node = randint(0, len(G_dinitz.nodes)-1) end_node = randint(0, len(G_dinitz.nodes)-1) while start_node == end_node: end_node = randint(0, len(G_dinitz.nodes)-1) # Run max-flow R_dinitz = dinitz(G_dinitz, start_node, end_node) R_gr = goldberg_rao(G_gr, start_node, end_node) # Check correctness d_mf = R_dinitz.graph["flow_value"] gr_mf = R_gr.graph["flow_value"] assert d_mf == gr_mf, f"Computed max flow in {name} graph is {d_mf}, but goldberg_rao function computed {gr_mf}"
def random_lobster(n, p1, p2, seed=None): """Returns a random lobster graph. A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes; setting `p2` to zero produces a caterpillar. Parameters ---------- n : int The expected number of nodes in the backbone p1 : float Probability of adding an edge to the backbone p2 : float Probability of adding an edge one level beyond backbone seed : integer, random_state, or None (default) Indicator of random number generation state. See :ref:`Randomness<randomness>`. """ # a necessary ingredient in any self-respecting graph library llen = int(2 * seed.random() * n + 0.5) L = path_graph(llen) # build caterpillar: add edges to path graph with probability p1 current_node = llen - 1 for n in range(llen): if seed.random() < p1: # add fuzzy caterpillar parts current_node += 1 L.add_edge(n, current_node) if seed.random() < p2: # add crunchy lobster bits current_node += 1 L.add_edge(current_node - 1, current_node) return L # voila, un lobster!
def random_lobster(n, p1, p2, seed=None): """Returns a random lobster graph. A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes; setting ``p2`` to zero produces a caterillar. Parameters ---------- n : int The expected number of nodes in the backbone p1 : float Probability of adding an edge to the backbone p2 : float Probability of adding an edge one level beyond backbone seed : int, optional Seed for random number generator (default=None). """ # a necessary ingredient in any self-respecting graph library if seed is not None: random.seed(seed) llen=int(2*random.random()*n + 0.5) L=path_graph(llen) L.name="random_lobster(%d,%s,%s)"%(n,p1,p2) # build caterpillar: add edges to path graph with probability p1 current_node=llen-1 for n in range(llen): if random.random()<p1: # add fuzzy caterpillar parts current_node+=1 L.add_edge(n,current_node) if random.random()<p2: # add crunchy lobster bits current_node+=1 L.add_edge(current_node-1,current_node) return L # voila, un lobster!
def truncated_tetrahedron_graph(create_using=None): """Return the skeleton of the truncated Platonic tetrahedron.""" G=path_graph(12, create_using) # G.add_edges_from([(1,3),(1,10),(2,7),(4,12),(5,12),(6,8),(9,11)]) G.add_edges_from([(0,2),(0,9),(1,6),(3,11),(4,11),(5,7),(8,10)]) G.name="Truncated Tetrahedron Graph" return G
def test_format_keyword(self): WP4 = nx.Graph() WP4.add_edges_from( (n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) A = nx.to_scipy_sparse_matrix(P4, format="csr") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="csc") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="coo") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="bsr") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="lil") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="dia") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format="dok") npt.assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense())
def get_graph(max_size): graph_type = np.random.randint(1, 5) num_nodes = np.random.randint(5, max(max_size, 5) + 1) if graph_type == 1: return path_graph(num_nodes), graph_type elif graph_type == 2: g = random_tree(num_nodes) max_degree = 0 for n in g.degree: max_degree = max(max_degree, n[1]) if max_degree <= 2: graph_type = 1 return g, graph_type elif graph_type == 3: part1 = np.random.randint(2, max(max_size / 2, 2) + 1) part2 = np.random.randint(3, max(max_size / 2, 3) + 1) return complete_bipartite_graph(part1, part2), graph_type elif graph_type == 4: return cycle_graph(num_nodes), graph_type else: sys.exit('Something unexpected happened!')
def test_graph_edit_distance(self): G0 = nx.Graph() G1 = path_graph(6) G2 = cycle_graph(6) G3 = wheel_graph(7) assert graph_edit_distance(G0, G0) == 0 assert graph_edit_distance(G0, G1) == 11 assert graph_edit_distance(G1, G0) == 11 assert graph_edit_distance(G0, G2) == 12 assert graph_edit_distance(G2, G0) == 12 assert graph_edit_distance(G0, G3) == 19 assert graph_edit_distance(G3, G0) == 19 assert graph_edit_distance(G1, G1) == 0 assert graph_edit_distance(G1, G2) == 1 assert graph_edit_distance(G2, G1) == 1 assert graph_edit_distance(G1, G3) == 8 assert graph_edit_distance(G3, G1) == 8 assert graph_edit_distance(G2, G2) == 0 assert graph_edit_distance(G2, G3) == 7 assert graph_edit_distance(G3, G2) == 7 assert graph_edit_distance(G3, G3) == 0
def truncated_tetrahedron_graph(create_using=None): """Return the skeleton of the truncated Platonic tetrahedron.""" G = path_graph(12, create_using) # G.add_edges_from([(1,3),(1,10),(2,7),(4,12),(5,12),(6,8),(9,11)]) G.add_edges_from([(0, 2), (0, 9), (1, 6), (3, 11), (4, 11), (5, 7), (8, 10)]) G.name = "Truncated Tetrahedron Graph" return G
def test_optimal_edit_paths(self): G1 = path_graph(3) G2 = cycle_graph(3) paths, cost = optimal_edit_paths(G1, G2) assert cost == 1 assert len(paths) == 6 def canonical(vertex_path, edge_path): return tuple(sorted(vertex_path)), tuple( sorted(edge_path, key=lambda x: (None in x, x))) expected_paths = [([(0, 0), (1, 1), (2, 2)], [((0, 1), (0, 1)), ((1, 2), (1, 2)), (None, (0, 2))]), ([(0, 0), (1, 2), (2, 1)], [((0, 1), (0, 2)), ((1, 2), (1, 2)), (None, (0, 1))]), ([(0, 1), (1, 0), (2, 2)], [((0, 1), (0, 1)), ((1, 2), (0, 2)), (None, (1, 2))]), ([(0, 1), (1, 2), (2, 0)], [((0, 1), (1, 2)), ((1, 2), (0, 2)), (None, (0, 1))]), ([(0, 2), (1, 0), (2, 1)], [((0, 1), (0, 2)), ((1, 2), (0, 1)), (None, (1, 2))]), ([(0, 2), (1, 1), (2, 0)], [((0, 1), (1, 2)), ((1, 2), (0, 1)), (None, (0, 2))])] assert ({canonical(*p) for p in paths} == {canonical(*p) for p in expected_paths})
def test_format_keyword_raise(self): with pytest.raises(nx.NetworkXError): WP4 = nx.Graph() WP4.add_edges_from( (n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) nx.to_scipy_sparse_matrix(P4, format="any_other")
def test_format_keyword(self): WP4 = nx.Graph() WP4.add_edges_from( (n,n+1,dict(weight=0.5,other=0.3)) for n in range(3) ) P4 = path_graph(4) A = nx.to_scipy_sparse_matrix(P4, format='csr') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='csc') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='coo') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='bsr') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='lil') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='dia') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='dok') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense())
def test_format_keyword(self): WP4 = nx.Graph() WP4.add_edges_from( (n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) A = nx.to_scipy_sparse_matrix(P4, format='csr') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='csc') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='coo') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='bsr') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='lil') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='dia') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) A = nx.to_scipy_sparse_matrix(P4, format='dok') np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense())
def test_nodelist(self): """Conversion from graph to matrix to graph with nodelist.""" P4 = path_graph(4) P3 = path_graph(3) nodelist = list(P3) A = nx.to_numpy_matrix(P4, nodelist=nodelist) GA = nx.Graph(A) self.assert_equal(GA, P3) assert nx.to_numpy_matrix(P3, nodelist=[]).shape == (0, 0) # Test nodelist duplicates. long_nodelist = nodelist + [0] pytest.raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=long_nodelist) # Test nodelist contains non-nodes nonnodelist = [-1, 0, 1, 2] pytest.raises(nx.NetworkXError, nx.to_numpy_matrix, P3, nodelist=nonnodelist)
def test_weight_keyword(self): WP4 = nx.Graph() WP4.add_edges_from( (n,n+1,dict(weight=0.5,other=0.3)) for n in range(3) ) P4 = path_graph(4) A = nx.to_numpy_matrix(P4) np_assert_equal(A, nx.to_numpy_matrix(WP4,weight=None)) np_assert_equal(0.5*A, nx.to_numpy_matrix(WP4)) np_assert_equal(0.3*A, nx.to_numpy_matrix(WP4,weight='other'))
def test_weight_keyword(self): WP4 = nx.Graph() WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) A = nx.to_numpy_array(P4) np_assert_equal(A, nx.to_numpy_array(WP4, weight=None)) np_assert_equal(0.5 * A, nx.to_numpy_array(WP4)) np_assert_equal(0.3 * A, nx.to_numpy_array(WP4, weight="other"))
def test_weight_keyword(self): WP4 = nx.Graph() WP4.add_edges_from((n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) A = nx.to_scipy_sparse_matrix(P4) np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4, weight=None).todense()) np_assert_equal(0.5 * A.todense(), nx.to_scipy_sparse_matrix(WP4).todense()) np_assert_equal(0.3 * A.todense(), nx.to_scipy_sparse_matrix(WP4, weight="other").todense())
def test_weight_keyword(self): WP4 = nx.Graph() WP4.add_edges_from( (n,n+1,dict(weight=0.5,other=0.3)) for n in range(3) ) P4 = path_graph(4) A = nx.to_scipy_sparse_matrix(P4) np_assert_equal(A.todense(), nx.to_scipy_sparse_matrix(WP4,weight=None).todense()) np_assert_equal(0.5*A.todense(), nx.to_scipy_sparse_matrix(WP4).todense()) np_assert_equal(0.3*A.todense(), nx.to_scipy_sparse_matrix(WP4,weight='other').todense())
def run_analysis_n_nodes(n, unit_cap, n_runs=3): print(f"Running analysis for {n} nodes...") graphs = [lambda: balanced_tree(2, int(round(np.log2(n)-1))), lambda: binomial_tree(int(round(np.log2(n)))), lambda: cycle_graph(n), lambda: path_graph(n), lambda: star_graph(n-1), lambda: random_regular_graph(3, n), lambda: random_regular_graph(5, n)] results_gr = {} results_dinitz = {} for graph, name in zip(graphs, names): # Initialize both graphs G_dinitz = graph() G_gr = G_dinitz.copy() total_time_gr = 0 total_time_dinitz = 0 for _ in range(n_runs): # Set random capacities of graph edges for u, v in G_dinitz.edges: cap = randint(1, 100) if not unit_cap else 1 G_dinitz.edges[u, v]["capacity"] = cap G_gr.edges[u, v]["capacity"] = cap # Pick random start and end node start_node = randint(0, len(G_dinitz.nodes)-1) end_node = randint(0, len(G_dinitz.nodes)-1) while start_node == end_node: end_node = randint(0, len(G_dinitz.nodes)-1) # Run max-flow init_time = time.time() R_dinitz = dinitz(G_dinitz, start_node, end_node) total_time_dinitz += time.time() - init_time init_time = time.time() R_gr = goldberg_rao(G_gr, start_node, end_node) total_time_gr += time.time() - init_time # Check correctness d_mf = R_dinitz.graph["flow_value"] gr_mf = R_gr.graph["flow_value"] if d_mf != gr_mf: vprint(f"\t\t\tComputed max flow in {name} graph is {d_mf}, but goldberg_rao function computed {gr_mf}".upper()) vprint(f"{name} with {len(G_gr.nodes)} nodes took {total_time_gr / n_runs} seconds with goldberg_rao") vprint(f"{name} with {len(G_dinitz.nodes)} nodes took {total_time_dinitz / n_runs} seconds with dinitz") results_gr[name] = total_time_gr / n_runs results_dinitz[name] = total_time_dinitz / n_runs return results_gr, results_dinitz
def random_lobster(n, p1, p2, create_using=None, seed=None): """Return a random lobster. A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes (p2=0). Parameters ---------- n : int The expected number of nodes in the backbone p1 : float Probability of adding an edge to the backbone p2 : float Probability of adding an edge one level beyond backbone create_using : graph, optional (default Graph) The graph instance used to build the graph. seed : int, optional Seed for random number generator (default=None). """ # a necessary ingredient in any self-respecting graph library if seed is not None: random.seed(seed) llen=int(2*random.random()*n + 0.5) if create_using is not None and create_using.is_directed(): raise nx.NetworkXError("Directed Graph not supported") L=path_graph(llen,create_using) L.name="random_lobster(%d,%s,%s)"%(n,p1,p2) # build caterpillar: add edges to path graph with probability p1 current_node=llen-1 for n in xrange(llen): if random.random()<p1: # add fuzzy caterpillar parts current_node+=1 L.add_edge(n,current_node) if random.random()<p2: # add crunchy lobster bits current_node+=1 L.add_edge(current_node-1,current_node) return L # voila, un lobster!
def random_lobster(n, p1, p2, create_using=None, seed=None): """Return a random lobster. A lobster is a tree that reduces to a caterpillar when pruning all leaf nodes. A caterpillar is a tree that reduces to a path graph when pruning all leaf nodes (p2=0). Parameters ---------- n : int The expected number of nodes in the backbone p1 : float Probability of adding an edge to the backbone p2 : float Probability of adding an edge one level beyond backbone create_using : graph, optional (default Graph) The graph instance used to build the graph. seed : int, optional Seed for random number generator (default=None). """ # a necessary ingredient in any self-respecting graph library if seed is not None: random.seed(seed) llen = int(2 * random.random() * n + 0.5) if create_using is not None and create_using.is_directed(): raise nx.NetworkXError("Directed Graph not supported") L = path_graph(llen, create_using) L.name = "random_lobster(%d,%s,%s)" % (n, p1, p2) # build caterpillar: add edges to path graph with probability p1 current_node = llen - 1 for n in range(llen): if random.random() < p1: # add fuzzy caterpillar parts current_node += 1 L.add_edge(n, current_node) if random.random() < p2: # add crunchy lobster bits current_node += 1 L.add_edge(current_node - 1, current_node) return L # voila, un lobster!
def run_analysis_n_nodes(n, unit_cap, n_runs=3): print(f"Running analysis for {n} nodes...") graphs = [ lambda: balanced_tree(2, int(round(np.log2(n) - 1))), lambda: binomial_tree(int(round(np.log2(n)))), lambda: cycle_graph(n), lambda: path_graph(n), lambda: star_graph(n - 1), lambda: random_regular_graph(3, n), lambda: random_regular_graph(5, n) ] results_dinitz = {} for graph, name in zip(graphs, names): # Initialize both graphs G_dinitz = graph() total_time_dinitz = 0 for _ in range(n_runs): # Set random capacities of graph edges for u, v in G_dinitz.edges: cap = randint(1, 100) if not unit_cap else 1 G_dinitz.edges[u, v]["capacity"] = cap # Pick random start and end node start_node = randint(0, len(G_dinitz.nodes) - 1) end_node = randint(0, len(G_dinitz.nodes) - 1) while start_node == end_node: end_node = randint(0, len(G_dinitz.nodes) - 1) # Run max-flow init_time = time.time() R_dinitz = dinitz(G_dinitz, start_node, end_node) total_time_dinitz += time.time() - init_time vprint( f"{name} with {len(G_dinitz.nodes)} nodes took {total_time_dinitz / n_runs} seconds with dinitz" ) results_dinitz[name] = total_time_dinitz / n_runs return results_dinitz
def test_format_keyword_fail(self): WP4 = nx.Graph() WP4.add_edges_from( (n,n+1,dict(weight=0.5,other=0.3)) for n in range(3) ) P4 = path_graph(4) nx.to_scipy_sparse_matrix(P4, format='any_other')
def test_format_keyword_fail(self): WP4 = nx.Graph() WP4.add_edges_from( (n, n + 1, dict(weight=0.5, other=0.3)) for n in range(3)) P4 = path_graph(4) nx.to_scipy_sparse_matrix(P4, format='any_other')