Fixed database typo and removed unnecessary class identifier.
This commit is contained in:
parent
00ad49a143
commit
45fb349a7d
5098 changed files with 952558 additions and 85 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,43 @@
|
|||
import networkx as nx
|
||||
from networkx.algorithms.approximation import average_clustering
|
||||
|
||||
# This approximation has to be be exact in regular graphs
|
||||
# with no triangles or with all possible triangles.
|
||||
|
||||
|
||||
def test_petersen():
|
||||
# Actual coefficient is 0
|
||||
G = nx.petersen_graph()
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == nx.average_clustering(G)
|
||||
|
||||
|
||||
def test_petersen_seed():
|
||||
# Actual coefficient is 0
|
||||
G = nx.petersen_graph()
|
||||
assert average_clustering(
|
||||
G, trials=int(len(G) / 2), seed=1
|
||||
) == nx.average_clustering(G)
|
||||
|
||||
|
||||
def test_tetrahedral():
|
||||
# Actual coefficient is 1
|
||||
G = nx.tetrahedral_graph()
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == nx.average_clustering(G)
|
||||
|
||||
|
||||
def test_dodecahedral():
|
||||
# Actual coefficient is 0
|
||||
G = nx.dodecahedral_graph()
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == nx.average_clustering(G)
|
||||
|
||||
|
||||
def test_empty():
|
||||
G = nx.empty_graph(5)
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == 0
|
||||
|
||||
|
||||
def test_complete():
|
||||
G = nx.complete_graph(5)
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == 1
|
||||
G = nx.complete_graph(7)
|
||||
assert average_clustering(G, trials=int(len(G) / 2)) == 1
|
|
@ -0,0 +1,107 @@
|
|||
"""Unit tests for the :mod:`networkx.algorithms.approximation.clique`
|
||||
module.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import networkx as nx
|
||||
from networkx.algorithms.approximation import max_clique
|
||||
from networkx.algorithms.approximation import clique_removal
|
||||
from networkx.algorithms.approximation import large_clique_size
|
||||
|
||||
|
||||
def is_independent_set(G, nodes):
|
||||
"""Returns True if and only if `nodes` is a clique in `G`.
|
||||
|
||||
`G` is a NetworkX graph. `nodes` is an iterable of nodes in
|
||||
`G`.
|
||||
|
||||
"""
|
||||
return G.subgraph(nodes).number_of_edges() == 0
|
||||
|
||||
|
||||
def is_clique(G, nodes):
|
||||
"""Returns True if and only if `nodes` is an independent set
|
||||
in `G`.
|
||||
|
||||
`G` is an undirected simple graph. `nodes` is an iterable of
|
||||
nodes in `G`.
|
||||
|
||||
"""
|
||||
H = G.subgraph(nodes)
|
||||
n = len(H)
|
||||
return H.number_of_edges() == n * (n - 1) // 2
|
||||
|
||||
|
||||
class TestCliqueRemoval:
|
||||
"""Unit tests for the
|
||||
:func:`~networkx.algorithms.approximation.clique_removal` function.
|
||||
|
||||
"""
|
||||
|
||||
def test_trivial_graph(self):
|
||||
G = nx.trivial_graph()
|
||||
independent_set, cliques = clique_removal(G)
|
||||
assert is_independent_set(G, independent_set)
|
||||
assert all(is_clique(G, clique) for clique in cliques)
|
||||
# In fact, we should only have 1-cliques, that is, singleton nodes.
|
||||
assert all(len(clique) == 1 for clique in cliques)
|
||||
|
||||
def test_complete_graph(self):
|
||||
G = nx.complete_graph(10)
|
||||
independent_set, cliques = clique_removal(G)
|
||||
assert is_independent_set(G, independent_set)
|
||||
assert all(is_clique(G, clique) for clique in cliques)
|
||||
|
||||
def test_barbell_graph(self):
|
||||
G = nx.barbell_graph(10, 5)
|
||||
independent_set, cliques = clique_removal(G)
|
||||
assert is_independent_set(G, independent_set)
|
||||
assert all(is_clique(G, clique) for clique in cliques)
|
||||
|
||||
|
||||
class TestMaxClique:
|
||||
"""Unit tests for the :func:`networkx.algorithms.approximation.max_clique`
|
||||
function.
|
||||
|
||||
"""
|
||||
|
||||
def test_null_graph(self):
|
||||
G = nx.null_graph()
|
||||
assert len(max_clique(G)) == 0
|
||||
|
||||
def test_complete_graph(self):
|
||||
graph = nx.complete_graph(30)
|
||||
# this should return the entire graph
|
||||
mc = max_clique(graph)
|
||||
assert 30 == len(mc)
|
||||
|
||||
def test_maximal_by_cardinality(self):
|
||||
"""Tests that the maximal clique is computed according to maximum
|
||||
cardinality of the sets.
|
||||
|
||||
For more information, see pull request #1531.
|
||||
|
||||
"""
|
||||
G = nx.complete_graph(5)
|
||||
G.add_edge(4, 5)
|
||||
clique = max_clique(G)
|
||||
assert len(clique) > 1
|
||||
|
||||
G = nx.lollipop_graph(30, 2)
|
||||
clique = max_clique(G)
|
||||
assert len(clique) > 2
|
||||
|
||||
|
||||
def test_large_clique_size():
|
||||
G = nx.complete_graph(9)
|
||||
nx.add_cycle(G, [9, 10, 11])
|
||||
G.add_edge(8, 9)
|
||||
G.add_edge(1, 12)
|
||||
G.add_node(13)
|
||||
|
||||
assert large_clique_size(G) == 9
|
||||
G.remove_node(5)
|
||||
assert large_clique_size(G) == 8
|
||||
G.remove_edge(2, 3)
|
||||
assert large_clique_size(G) == 7
|
|
@ -0,0 +1,199 @@
|
|||
import pytest
|
||||
|
||||
import networkx as nx
|
||||
from networkx.algorithms import approximation as approx
|
||||
|
||||
|
||||
def test_global_node_connectivity():
|
||||
# Figure 1 chapter on Connectivity
|
||||
G = nx.Graph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2),
|
||||
(1, 3),
|
||||
(1, 4),
|
||||
(1, 5),
|
||||
(2, 3),
|
||||
(2, 6),
|
||||
(3, 4),
|
||||
(3, 6),
|
||||
(4, 6),
|
||||
(4, 7),
|
||||
(5, 7),
|
||||
(6, 8),
|
||||
(6, 9),
|
||||
(7, 8),
|
||||
(7, 10),
|
||||
(8, 11),
|
||||
(9, 10),
|
||||
(9, 11),
|
||||
(10, 11),
|
||||
]
|
||||
)
|
||||
assert 2 == approx.local_node_connectivity(G, 1, 11)
|
||||
assert 2 == approx.node_connectivity(G)
|
||||
assert 2 == approx.node_connectivity(G, 1, 11)
|
||||
|
||||
|
||||
def test_white_harary1():
|
||||
# Figure 1b white and harary (2001)
|
||||
# A graph with high adhesion (edge connectivity) and low cohesion
|
||||
# (node connectivity)
|
||||
G = nx.disjoint_union(nx.complete_graph(4), nx.complete_graph(4))
|
||||
G.remove_node(7)
|
||||
for i in range(4, 7):
|
||||
G.add_edge(0, i)
|
||||
G = nx.disjoint_union(G, nx.complete_graph(4))
|
||||
G.remove_node(G.order() - 1)
|
||||
for i in range(7, 10):
|
||||
G.add_edge(0, i)
|
||||
assert 1 == approx.node_connectivity(G)
|
||||
|
||||
|
||||
def test_complete_graphs():
|
||||
for n in range(5, 25, 5):
|
||||
G = nx.complete_graph(n)
|
||||
assert n - 1 == approx.node_connectivity(G)
|
||||
assert n - 1 == approx.node_connectivity(G, 0, 3)
|
||||
|
||||
|
||||
def test_empty_graphs():
|
||||
for k in range(5, 25, 5):
|
||||
G = nx.empty_graph(k)
|
||||
assert 0 == approx.node_connectivity(G)
|
||||
assert 0 == approx.node_connectivity(G, 0, 3)
|
||||
|
||||
|
||||
def test_petersen():
|
||||
G = nx.petersen_graph()
|
||||
assert 3 == approx.node_connectivity(G)
|
||||
assert 3 == approx.node_connectivity(G, 0, 5)
|
||||
|
||||
|
||||
# Approximation fails with tutte graph
|
||||
# def test_tutte():
|
||||
# G = nx.tutte_graph()
|
||||
# assert_equal(3, approx.node_connectivity(G))
|
||||
|
||||
|
||||
def test_dodecahedral():
|
||||
G = nx.dodecahedral_graph()
|
||||
assert 3 == approx.node_connectivity(G)
|
||||
assert 3 == approx.node_connectivity(G, 0, 5)
|
||||
|
||||
|
||||
def test_octahedral():
|
||||
G = nx.octahedral_graph()
|
||||
assert 4 == approx.node_connectivity(G)
|
||||
assert 4 == approx.node_connectivity(G, 0, 5)
|
||||
|
||||
|
||||
# Approximation can fail with icosahedral graph depending
|
||||
# on iteration order.
|
||||
# def test_icosahedral():
|
||||
# G=nx.icosahedral_graph()
|
||||
# assert_equal(5, approx.node_connectivity(G))
|
||||
# assert_equal(5, approx.node_connectivity(G, 0, 5))
|
||||
|
||||
|
||||
def test_only_source():
|
||||
G = nx.complete_graph(5)
|
||||
pytest.raises(nx.NetworkXError, approx.node_connectivity, G, s=0)
|
||||
|
||||
|
||||
def test_only_target():
|
||||
G = nx.complete_graph(5)
|
||||
pytest.raises(nx.NetworkXError, approx.node_connectivity, G, t=0)
|
||||
|
||||
|
||||
def test_missing_source():
|
||||
G = nx.path_graph(4)
|
||||
pytest.raises(nx.NetworkXError, approx.node_connectivity, G, 10, 1)
|
||||
|
||||
|
||||
def test_missing_target():
|
||||
G = nx.path_graph(4)
|
||||
pytest.raises(nx.NetworkXError, approx.node_connectivity, G, 1, 10)
|
||||
|
||||
|
||||
def test_source_equals_target():
|
||||
G = nx.complete_graph(5)
|
||||
pytest.raises(nx.NetworkXError, approx.local_node_connectivity, G, 0, 0)
|
||||
|
||||
|
||||
def test_directed_node_connectivity():
|
||||
G = nx.cycle_graph(10, create_using=nx.DiGraph()) # only one direction
|
||||
D = nx.cycle_graph(10).to_directed() # 2 reciprocal edges
|
||||
assert 1 == approx.node_connectivity(G)
|
||||
assert 1 == approx.node_connectivity(G, 1, 4)
|
||||
assert 2 == approx.node_connectivity(D)
|
||||
assert 2 == approx.node_connectivity(D, 1, 4)
|
||||
|
||||
|
||||
class TestAllPairsNodeConnectivityApprox:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.path = nx.path_graph(7)
|
||||
cls.directed_path = nx.path_graph(7, create_using=nx.DiGraph())
|
||||
cls.cycle = nx.cycle_graph(7)
|
||||
cls.directed_cycle = nx.cycle_graph(7, create_using=nx.DiGraph())
|
||||
cls.gnp = nx.gnp_random_graph(30, 0.1)
|
||||
cls.directed_gnp = nx.gnp_random_graph(30, 0.1, directed=True)
|
||||
cls.K20 = nx.complete_graph(20)
|
||||
cls.K10 = nx.complete_graph(10)
|
||||
cls.K5 = nx.complete_graph(5)
|
||||
cls.G_list = [
|
||||
cls.path,
|
||||
cls.directed_path,
|
||||
cls.cycle,
|
||||
cls.directed_cycle,
|
||||
cls.gnp,
|
||||
cls.directed_gnp,
|
||||
cls.K10,
|
||||
cls.K5,
|
||||
cls.K20,
|
||||
]
|
||||
|
||||
def test_cycles(self):
|
||||
K_undir = approx.all_pairs_node_connectivity(self.cycle)
|
||||
for source in K_undir:
|
||||
for target, k in K_undir[source].items():
|
||||
assert k == 2
|
||||
K_dir = approx.all_pairs_node_connectivity(self.directed_cycle)
|
||||
for source in K_dir:
|
||||
for target, k in K_dir[source].items():
|
||||
assert k == 1
|
||||
|
||||
def test_complete(self):
|
||||
for G in [self.K10, self.K5, self.K20]:
|
||||
K = approx.all_pairs_node_connectivity(G)
|
||||
for source in K:
|
||||
for target, k in K[source].items():
|
||||
assert k == len(G) - 1
|
||||
|
||||
def test_paths(self):
|
||||
K_undir = approx.all_pairs_node_connectivity(self.path)
|
||||
for source in K_undir:
|
||||
for target, k in K_undir[source].items():
|
||||
assert k == 1
|
||||
K_dir = approx.all_pairs_node_connectivity(self.directed_path)
|
||||
for source in K_dir:
|
||||
for target, k in K_dir[source].items():
|
||||
if source < target:
|
||||
assert k == 1
|
||||
else:
|
||||
assert k == 0
|
||||
|
||||
def test_cutoff(self):
|
||||
for G in [self.K10, self.K5, self.K20]:
|
||||
for mp in [2, 3, 4]:
|
||||
paths = approx.all_pairs_node_connectivity(G, cutoff=mp)
|
||||
for source in paths:
|
||||
for target, K in paths[source].items():
|
||||
assert K == mp
|
||||
|
||||
def test_all_pairs_connectivity_nbunch(self):
|
||||
G = nx.complete_graph(5)
|
||||
nbunch = [0, 2, 3]
|
||||
C = approx.all_pairs_node_connectivity(G, nbunch=nbunch)
|
||||
assert len(C) == len(nbunch)
|
|
@ -0,0 +1,65 @@
|
|||
import networkx as nx
|
||||
from networkx.algorithms.approximation import min_weighted_dominating_set
|
||||
from networkx.algorithms.approximation import min_edge_dominating_set
|
||||
|
||||
|
||||
class TestMinWeightDominatingSet:
|
||||
def test_min_weighted_dominating_set(self):
|
||||
graph = nx.Graph()
|
||||
graph.add_edge(1, 2)
|
||||
graph.add_edge(1, 5)
|
||||
graph.add_edge(2, 3)
|
||||
graph.add_edge(2, 5)
|
||||
graph.add_edge(3, 4)
|
||||
graph.add_edge(3, 6)
|
||||
graph.add_edge(5, 6)
|
||||
|
||||
vertices = {1, 2, 3, 4, 5, 6}
|
||||
# due to ties, this might be hard to test tight bounds
|
||||
dom_set = min_weighted_dominating_set(graph)
|
||||
for vertex in vertices - dom_set:
|
||||
neighbors = set(graph.neighbors(vertex))
|
||||
assert len(neighbors & dom_set) > 0, "Non dominating set found!"
|
||||
|
||||
def test_star_graph(self):
|
||||
"""Tests that an approximate dominating set for the star graph,
|
||||
even when the center node does not have the smallest integer
|
||||
label, gives just the center node.
|
||||
|
||||
For more information, see #1527.
|
||||
|
||||
"""
|
||||
# Create a star graph in which the center node has the highest
|
||||
# label instead of the lowest.
|
||||
G = nx.star_graph(10)
|
||||
G = nx.relabel_nodes(G, {0: 9, 9: 0})
|
||||
assert min_weighted_dominating_set(G) == {9}
|
||||
|
||||
def test_min_edge_dominating_set(self):
|
||||
graph = nx.path_graph(5)
|
||||
dom_set = min_edge_dominating_set(graph)
|
||||
|
||||
# this is a crappy way to test, but good enough for now.
|
||||
for edge in graph.edges():
|
||||
if edge in dom_set:
|
||||
continue
|
||||
else:
|
||||
u, v = edge
|
||||
found = False
|
||||
for dom_edge in dom_set:
|
||||
found |= u == dom_edge[0] or u == dom_edge[1]
|
||||
assert found, "Non adjacent edge found!"
|
||||
|
||||
graph = nx.complete_graph(10)
|
||||
dom_set = min_edge_dominating_set(graph)
|
||||
|
||||
# this is a crappy way to test, but good enough for now.
|
||||
for edge in graph.edges():
|
||||
if edge in dom_set:
|
||||
continue
|
||||
else:
|
||||
u, v = edge
|
||||
found = False
|
||||
for dom_edge in dom_set:
|
||||
found |= u == dom_edge[0] or u == dom_edge[1]
|
||||
assert found, "Non adjacent edge found!"
|
|
@ -0,0 +1,8 @@
|
|||
import networkx as nx
|
||||
import networkx.algorithms.approximation as a
|
||||
|
||||
|
||||
def test_independent_set():
|
||||
# smoke test
|
||||
G = nx.Graph()
|
||||
assert len(a.maximum_independent_set(G)) == 0
|
|
@ -0,0 +1,300 @@
|
|||
# Test for approximation to k-components algorithm
|
||||
import pytest
|
||||
import networkx as nx
|
||||
from networkx.algorithms.approximation import k_components
|
||||
from networkx.algorithms.approximation.kcomponents import _AntiGraph, _same
|
||||
|
||||
|
||||
def build_k_number_dict(k_components):
|
||||
k_num = {}
|
||||
for k, comps in sorted(k_components.items()):
|
||||
for comp in comps:
|
||||
for node in comp:
|
||||
k_num[node] = k
|
||||
return k_num
|
||||
|
||||
|
||||
##
|
||||
# Some nice synthetic graphs
|
||||
##
|
||||
|
||||
|
||||
def graph_example_1():
|
||||
G = nx.convert_node_labels_to_integers(
|
||||
nx.grid_graph([5, 5]), label_attribute="labels"
|
||||
)
|
||||
rlabels = nx.get_node_attributes(G, "labels")
|
||||
labels = {v: k for k, v in rlabels.items()}
|
||||
|
||||
for nodes in [
|
||||
(labels[(0, 0)], labels[(1, 0)]),
|
||||
(labels[(0, 4)], labels[(1, 4)]),
|
||||
(labels[(3, 0)], labels[(4, 0)]),
|
||||
(labels[(3, 4)], labels[(4, 4)]),
|
||||
]:
|
||||
new_node = G.order() + 1
|
||||
# Petersen graph is triconnected
|
||||
P = nx.petersen_graph()
|
||||
G = nx.disjoint_union(G, P)
|
||||
# Add two edges between the grid and P
|
||||
G.add_edge(new_node + 1, nodes[0])
|
||||
G.add_edge(new_node, nodes[1])
|
||||
# K5 is 4-connected
|
||||
K = nx.complete_graph(5)
|
||||
G = nx.disjoint_union(G, K)
|
||||
# Add three edges between P and K5
|
||||
G.add_edge(new_node + 2, new_node + 11)
|
||||
G.add_edge(new_node + 3, new_node + 12)
|
||||
G.add_edge(new_node + 4, new_node + 13)
|
||||
# Add another K5 sharing a node
|
||||
G = nx.disjoint_union(G, K)
|
||||
nbrs = G[new_node + 10]
|
||||
G.remove_node(new_node + 10)
|
||||
for nbr in nbrs:
|
||||
G.add_edge(new_node + 17, nbr)
|
||||
G.add_edge(new_node + 16, new_node + 5)
|
||||
return G
|
||||
|
||||
|
||||
def torrents_and_ferraro_graph():
|
||||
G = nx.convert_node_labels_to_integers(
|
||||
nx.grid_graph([5, 5]), label_attribute="labels"
|
||||
)
|
||||
rlabels = nx.get_node_attributes(G, "labels")
|
||||
labels = {v: k for k, v in rlabels.items()}
|
||||
|
||||
for nodes in [(labels[(0, 4)], labels[(1, 4)]), (labels[(3, 4)], labels[(4, 4)])]:
|
||||
new_node = G.order() + 1
|
||||
# Petersen graph is triconnected
|
||||
P = nx.petersen_graph()
|
||||
G = nx.disjoint_union(G, P)
|
||||
# Add two edges between the grid and P
|
||||
G.add_edge(new_node + 1, nodes[0])
|
||||
G.add_edge(new_node, nodes[1])
|
||||
# K5 is 4-connected
|
||||
K = nx.complete_graph(5)
|
||||
G = nx.disjoint_union(G, K)
|
||||
# Add three edges between P and K5
|
||||
G.add_edge(new_node + 2, new_node + 11)
|
||||
G.add_edge(new_node + 3, new_node + 12)
|
||||
G.add_edge(new_node + 4, new_node + 13)
|
||||
# Add another K5 sharing a node
|
||||
G = nx.disjoint_union(G, K)
|
||||
nbrs = G[new_node + 10]
|
||||
G.remove_node(new_node + 10)
|
||||
for nbr in nbrs:
|
||||
G.add_edge(new_node + 17, nbr)
|
||||
# Commenting this makes the graph not biconnected !!
|
||||
# This stupid mistake make one reviewer very angry :P
|
||||
G.add_edge(new_node + 16, new_node + 8)
|
||||
|
||||
for nodes in [(labels[(0, 0)], labels[(1, 0)]), (labels[(3, 0)], labels[(4, 0)])]:
|
||||
new_node = G.order() + 1
|
||||
# Petersen graph is triconnected
|
||||
P = nx.petersen_graph()
|
||||
G = nx.disjoint_union(G, P)
|
||||
# Add two edges between the grid and P
|
||||
G.add_edge(new_node + 1, nodes[0])
|
||||
G.add_edge(new_node, nodes[1])
|
||||
# K5 is 4-connected
|
||||
K = nx.complete_graph(5)
|
||||
G = nx.disjoint_union(G, K)
|
||||
# Add three edges between P and K5
|
||||
G.add_edge(new_node + 2, new_node + 11)
|
||||
G.add_edge(new_node + 3, new_node + 12)
|
||||
G.add_edge(new_node + 4, new_node + 13)
|
||||
# Add another K5 sharing two nodes
|
||||
G = nx.disjoint_union(G, K)
|
||||
nbrs = G[new_node + 10]
|
||||
G.remove_node(new_node + 10)
|
||||
for nbr in nbrs:
|
||||
G.add_edge(new_node + 17, nbr)
|
||||
nbrs2 = G[new_node + 9]
|
||||
G.remove_node(new_node + 9)
|
||||
for nbr in nbrs2:
|
||||
G.add_edge(new_node + 18, nbr)
|
||||
return G
|
||||
|
||||
|
||||
# Helper function
|
||||
|
||||
|
||||
def _check_connectivity(G):
|
||||
result = k_components(G)
|
||||
for k, components in result.items():
|
||||
if k < 3:
|
||||
continue
|
||||
for component in components:
|
||||
C = G.subgraph(component)
|
||||
K = nx.node_connectivity(C)
|
||||
assert K >= k
|
||||
|
||||
|
||||
def test_torrents_and_ferraro_graph():
|
||||
G = torrents_and_ferraro_graph()
|
||||
_check_connectivity(G)
|
||||
|
||||
|
||||
def test_example_1():
|
||||
G = graph_example_1()
|
||||
_check_connectivity(G)
|
||||
|
||||
|
||||
def test_karate_0():
|
||||
G = nx.karate_club_graph()
|
||||
_check_connectivity(G)
|
||||
|
||||
|
||||
def test_karate_1():
|
||||
karate_k_num = {
|
||||
0: 4,
|
||||
1: 4,
|
||||
2: 4,
|
||||
3: 4,
|
||||
4: 3,
|
||||
5: 3,
|
||||
6: 3,
|
||||
7: 4,
|
||||
8: 4,
|
||||
9: 2,
|
||||
10: 3,
|
||||
11: 1,
|
||||
12: 2,
|
||||
13: 4,
|
||||
14: 2,
|
||||
15: 2,
|
||||
16: 2,
|
||||
17: 2,
|
||||
18: 2,
|
||||
19: 3,
|
||||
20: 2,
|
||||
21: 2,
|
||||
22: 2,
|
||||
23: 3,
|
||||
24: 3,
|
||||
25: 3,
|
||||
26: 2,
|
||||
27: 3,
|
||||
28: 3,
|
||||
29: 3,
|
||||
30: 4,
|
||||
31: 3,
|
||||
32: 4,
|
||||
33: 4,
|
||||
}
|
||||
approx_karate_k_num = karate_k_num.copy()
|
||||
approx_karate_k_num[24] = 2
|
||||
approx_karate_k_num[25] = 2
|
||||
G = nx.karate_club_graph()
|
||||
k_comps = k_components(G)
|
||||
k_num = build_k_number_dict(k_comps)
|
||||
assert k_num in (karate_k_num, approx_karate_k_num)
|
||||
|
||||
|
||||
def test_example_1_detail_3_and_4():
|
||||
G = graph_example_1()
|
||||
result = k_components(G)
|
||||
# In this example graph there are 8 3-components, 4 with 15 nodes
|
||||
# and 4 with 5 nodes.
|
||||
assert len(result[3]) == 8
|
||||
assert len([c for c in result[3] if len(c) == 15]) == 4
|
||||
assert len([c for c in result[3] if len(c) == 5]) == 4
|
||||
# There are also 8 4-components all with 5 nodes.
|
||||
assert len(result[4]) == 8
|
||||
assert all(len(c) == 5 for c in result[4])
|
||||
# Finally check that the k-components detected have actually node
|
||||
# connectivity >= k.
|
||||
for k, components in result.items():
|
||||
if k < 3:
|
||||
continue
|
||||
for component in components:
|
||||
K = nx.node_connectivity(G.subgraph(component))
|
||||
assert K >= k
|
||||
|
||||
|
||||
def test_directed():
|
||||
with pytest.raises(nx.NetworkXNotImplemented):
|
||||
G = nx.gnp_random_graph(10, 0.4, directed=True)
|
||||
kc = k_components(G)
|
||||
|
||||
|
||||
def test_same():
|
||||
equal = {"A": 2, "B": 2, "C": 2}
|
||||
slightly_different = {"A": 2, "B": 1, "C": 2}
|
||||
different = {"A": 2, "B": 8, "C": 18}
|
||||
assert _same(equal)
|
||||
assert not _same(slightly_different)
|
||||
assert _same(slightly_different, tol=1)
|
||||
assert not _same(different)
|
||||
assert not _same(different, tol=4)
|
||||
|
||||
|
||||
class TestAntiGraph:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
cls.Gnp = nx.gnp_random_graph(20, 0.8)
|
||||
cls.Anp = _AntiGraph(nx.complement(cls.Gnp))
|
||||
cls.Gd = nx.davis_southern_women_graph()
|
||||
cls.Ad = _AntiGraph(nx.complement(cls.Gd))
|
||||
cls.Gk = nx.karate_club_graph()
|
||||
cls.Ak = _AntiGraph(nx.complement(cls.Gk))
|
||||
cls.GA = [(cls.Gnp, cls.Anp), (cls.Gd, cls.Ad), (cls.Gk, cls.Ak)]
|
||||
|
||||
def test_size(self):
|
||||
for G, A in self.GA:
|
||||
n = G.order()
|
||||
s = len(list(G.edges())) + len(list(A.edges()))
|
||||
assert s == (n * (n - 1)) / 2
|
||||
|
||||
def test_degree(self):
|
||||
for G, A in self.GA:
|
||||
assert sorted(G.degree()) == sorted(A.degree())
|
||||
|
||||
def test_core_number(self):
|
||||
for G, A in self.GA:
|
||||
assert nx.core_number(G) == nx.core_number(A)
|
||||
|
||||
def test_connected_components(self):
|
||||
for G, A in self.GA:
|
||||
gc = [set(c) for c in nx.connected_components(G)]
|
||||
ac = [set(c) for c in nx.connected_components(A)]
|
||||
for comp in ac:
|
||||
assert comp in gc
|
||||
|
||||
def test_adj(self):
|
||||
for G, A in self.GA:
|
||||
for n, nbrs in G.adj.items():
|
||||
a_adj = sorted((n, sorted(ad)) for n, ad in A.adj.items())
|
||||
g_adj = sorted((n, sorted(ad)) for n, ad in G.adj.items())
|
||||
assert a_adj == g_adj
|
||||
|
||||
def test_adjacency(self):
|
||||
for G, A in self.GA:
|
||||
a_adj = list(A.adjacency())
|
||||
for n, nbrs in G.adjacency():
|
||||
assert (n, set(nbrs)) in a_adj
|
||||
|
||||
def test_neighbors(self):
|
||||
for G, A in self.GA:
|
||||
node = list(G.nodes())[0]
|
||||
assert set(G.neighbors(node)) == set(A.neighbors(node))
|
||||
|
||||
def test_node_not_in_graph(self):
|
||||
for G, A in self.GA:
|
||||
node = "non_existent_node"
|
||||
pytest.raises(nx.NetworkXError, A.neighbors, node)
|
||||
pytest.raises(nx.NetworkXError, G.neighbors, node)
|
||||
|
||||
def test_degree_thingraph(self):
|
||||
for G, A in self.GA:
|
||||
node = list(G.nodes())[0]
|
||||
nodes = list(G.nodes())[1:4]
|
||||
assert G.degree(node) == A.degree(node)
|
||||
assert sum(d for n, d in G.degree()) == sum(d for n, d in A.degree())
|
||||
# AntiGraph is a ThinGraph, so all the weights are 1
|
||||
assert sum(d for n, d in A.degree()) == sum(
|
||||
d for n, d in A.degree(weight="weight")
|
||||
)
|
||||
assert sum(d for n, d in G.degree(nodes)) == sum(
|
||||
d for n, d in A.degree(nodes)
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
import networkx as nx
|
||||
import networkx.algorithms.approximation as a
|
||||
|
||||
|
||||
def test_min_maximal_matching():
|
||||
# smoke test
|
||||
G = nx.Graph()
|
||||
assert len(a.min_maximal_matching(G)) == 0
|
|
@ -0,0 +1,31 @@
|
|||
import networkx as nx
|
||||
import networkx.algorithms.approximation as apxa
|
||||
|
||||
|
||||
def test_ramsey():
|
||||
# this should only find the complete graph
|
||||
graph = nx.complete_graph(10)
|
||||
c, i = apxa.ramsey_R2(graph)
|
||||
cdens = nx.density(graph.subgraph(c))
|
||||
assert cdens == 1.0, "clique not correctly found by ramsey!"
|
||||
idens = nx.density(graph.subgraph(i))
|
||||
assert idens == 0.0, "i-set not correctly found by ramsey!"
|
||||
|
||||
# this trival graph has no cliques. should just find i-sets
|
||||
graph = nx.trivial_graph()
|
||||
c, i = apxa.ramsey_R2(graph)
|
||||
assert c == {0}, "clique not correctly found by ramsey!"
|
||||
assert i == {0}, "i-set not correctly found by ramsey!"
|
||||
|
||||
graph = nx.barbell_graph(10, 5, nx.Graph())
|
||||
c, i = apxa.ramsey_R2(graph)
|
||||
cdens = nx.density(graph.subgraph(c))
|
||||
assert cdens == 1.0, "clique not correctly found by ramsey!"
|
||||
idens = nx.density(graph.subgraph(i))
|
||||
assert idens == 0.0, "i-set not correctly found by ramsey!"
|
||||
|
||||
# add self-loops and test again
|
||||
graph.add_edges_from([(n, n) for n in range(0, len(graph), 2)])
|
||||
cc, ii = apxa.ramsey_R2(graph)
|
||||
assert cc == c
|
||||
assert ii == i
|
|
@ -0,0 +1,83 @@
|
|||
import pytest
|
||||
import networkx as nx
|
||||
from networkx.algorithms.approximation.steinertree import metric_closure
|
||||
from networkx.algorithms.approximation.steinertree import steiner_tree
|
||||
from networkx.testing.utils import assert_edges_equal
|
||||
|
||||
|
||||
class TestSteinerTree:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
G = nx.Graph()
|
||||
G.add_edge(1, 2, weight=10)
|
||||
G.add_edge(2, 3, weight=10)
|
||||
G.add_edge(3, 4, weight=10)
|
||||
G.add_edge(4, 5, weight=10)
|
||||
G.add_edge(5, 6, weight=10)
|
||||
G.add_edge(2, 7, weight=1)
|
||||
G.add_edge(7, 5, weight=1)
|
||||
cls.G = G
|
||||
cls.term_nodes = [1, 2, 3, 4, 5]
|
||||
|
||||
def test_connected_metric_closure(self):
|
||||
G = self.G.copy()
|
||||
G.add_node(100)
|
||||
pytest.raises(nx.NetworkXError, metric_closure, G)
|
||||
|
||||
def test_metric_closure(self):
|
||||
M = metric_closure(self.G)
|
||||
mc = [
|
||||
(1, 2, {"distance": 10, "path": [1, 2]}),
|
||||
(1, 3, {"distance": 20, "path": [1, 2, 3]}),
|
||||
(1, 4, {"distance": 22, "path": [1, 2, 7, 5, 4]}),
|
||||
(1, 5, {"distance": 12, "path": [1, 2, 7, 5]}),
|
||||
(1, 6, {"distance": 22, "path": [1, 2, 7, 5, 6]}),
|
||||
(1, 7, {"distance": 11, "path": [1, 2, 7]}),
|
||||
(2, 3, {"distance": 10, "path": [2, 3]}),
|
||||
(2, 4, {"distance": 12, "path": [2, 7, 5, 4]}),
|
||||
(2, 5, {"distance": 2, "path": [2, 7, 5]}),
|
||||
(2, 6, {"distance": 12, "path": [2, 7, 5, 6]}),
|
||||
(2, 7, {"distance": 1, "path": [2, 7]}),
|
||||
(3, 4, {"distance": 10, "path": [3, 4]}),
|
||||
(3, 5, {"distance": 12, "path": [3, 2, 7, 5]}),
|
||||
(3, 6, {"distance": 22, "path": [3, 2, 7, 5, 6]}),
|
||||
(3, 7, {"distance": 11, "path": [3, 2, 7]}),
|
||||
(4, 5, {"distance": 10, "path": [4, 5]}),
|
||||
(4, 6, {"distance": 20, "path": [4, 5, 6]}),
|
||||
(4, 7, {"distance": 11, "path": [4, 5, 7]}),
|
||||
(5, 6, {"distance": 10, "path": [5, 6]}),
|
||||
(5, 7, {"distance": 1, "path": [5, 7]}),
|
||||
(6, 7, {"distance": 11, "path": [6, 5, 7]}),
|
||||
]
|
||||
assert_edges_equal(list(M.edges(data=True)), mc)
|
||||
|
||||
def test_steiner_tree(self):
|
||||
S = steiner_tree(self.G, self.term_nodes)
|
||||
expected_steiner_tree = [
|
||||
(1, 2, {"weight": 10}),
|
||||
(2, 3, {"weight": 10}),
|
||||
(2, 7, {"weight": 1}),
|
||||
(3, 4, {"weight": 10}),
|
||||
(5, 7, {"weight": 1}),
|
||||
]
|
||||
assert_edges_equal(list(S.edges(data=True)), expected_steiner_tree)
|
||||
|
||||
def test_multigraph_steiner_tree(self):
|
||||
G = nx.MultiGraph()
|
||||
G.add_edges_from(
|
||||
[
|
||||
(1, 2, 0, {"weight": 1}),
|
||||
(2, 3, 0, {"weight": 999}),
|
||||
(2, 3, 1, {"weight": 1}),
|
||||
(3, 4, 0, {"weight": 1}),
|
||||
(3, 5, 0, {"weight": 1}),
|
||||
]
|
||||
)
|
||||
terminal_nodes = [2, 4, 5]
|
||||
expected_edges = [
|
||||
(2, 3, 1, {"weight": 1}), # edge with key 1 has lower weight
|
||||
(3, 4, 0, {"weight": 1}),
|
||||
(3, 5, 0, {"weight": 1}),
|
||||
]
|
||||
T = steiner_tree(G, terminal_nodes)
|
||||
assert_edges_equal(T.edges(data=True, keys=True), expected_edges)
|
|
@ -0,0 +1,269 @@
|
|||
import networkx as nx
|
||||
from networkx.algorithms.approximation import treewidth_min_degree
|
||||
from networkx.algorithms.approximation import treewidth_min_fill_in
|
||||
from networkx.algorithms.approximation.treewidth import min_fill_in_heuristic
|
||||
from networkx.algorithms.approximation.treewidth import MinDegreeHeuristic
|
||||
import itertools
|
||||
|
||||
|
||||
def is_tree_decomp(graph, decomp):
|
||||
"""Check if the given tree decomposition is valid."""
|
||||
for x in graph.nodes():
|
||||
appear_once = False
|
||||
for bag in decomp.nodes():
|
||||
if x in bag:
|
||||
appear_once = True
|
||||
break
|
||||
assert appear_once
|
||||
|
||||
# Check if each connected pair of nodes are at least once together in a bag
|
||||
for (x, y) in graph.edges():
|
||||
appear_together = False
|
||||
for bag in decomp.nodes():
|
||||
if x in bag and y in bag:
|
||||
appear_together = True
|
||||
break
|
||||
assert appear_together
|
||||
|
||||
# Check if the nodes associated with vertex v form a connected subset of T
|
||||
for v in graph.nodes():
|
||||
subset = []
|
||||
for bag in decomp.nodes():
|
||||
if v in bag:
|
||||
subset.append(bag)
|
||||
sub_graph = decomp.subgraph(subset)
|
||||
assert nx.is_connected(sub_graph)
|
||||
|
||||
|
||||
class TestTreewidthMinDegree:
|
||||
"""Unit tests for the min_degree function"""
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
"""Setup for different kinds of trees"""
|
||||
cls.complete = nx.Graph()
|
||||
cls.complete.add_edge(1, 2)
|
||||
cls.complete.add_edge(2, 3)
|
||||
cls.complete.add_edge(1, 3)
|
||||
|
||||
cls.small_tree = nx.Graph()
|
||||
cls.small_tree.add_edge(1, 3)
|
||||
cls.small_tree.add_edge(4, 3)
|
||||
cls.small_tree.add_edge(2, 3)
|
||||
cls.small_tree.add_edge(3, 5)
|
||||
cls.small_tree.add_edge(5, 6)
|
||||
cls.small_tree.add_edge(5, 7)
|
||||
cls.small_tree.add_edge(6, 7)
|
||||
|
||||
cls.deterministic_graph = nx.Graph()
|
||||
cls.deterministic_graph.add_edge(0, 1) # deg(0) = 1
|
||||
|
||||
cls.deterministic_graph.add_edge(1, 2) # deg(1) = 2
|
||||
|
||||
cls.deterministic_graph.add_edge(2, 3)
|
||||
cls.deterministic_graph.add_edge(2, 4) # deg(2) = 3
|
||||
|
||||
cls.deterministic_graph.add_edge(3, 4)
|
||||
cls.deterministic_graph.add_edge(3, 5)
|
||||
cls.deterministic_graph.add_edge(3, 6) # deg(3) = 4
|
||||
|
||||
cls.deterministic_graph.add_edge(4, 5)
|
||||
cls.deterministic_graph.add_edge(4, 6)
|
||||
cls.deterministic_graph.add_edge(4, 7) # deg(4) = 5
|
||||
|
||||
cls.deterministic_graph.add_edge(5, 6)
|
||||
cls.deterministic_graph.add_edge(5, 7)
|
||||
cls.deterministic_graph.add_edge(5, 8)
|
||||
cls.deterministic_graph.add_edge(5, 9) # deg(5) = 6
|
||||
|
||||
cls.deterministic_graph.add_edge(6, 7)
|
||||
cls.deterministic_graph.add_edge(6, 8)
|
||||
cls.deterministic_graph.add_edge(6, 9) # deg(6) = 6
|
||||
|
||||
cls.deterministic_graph.add_edge(7, 8)
|
||||
cls.deterministic_graph.add_edge(7, 9) # deg(7) = 5
|
||||
|
||||
cls.deterministic_graph.add_edge(8, 9) # deg(8) = 4
|
||||
|
||||
def test_petersen_graph(self):
|
||||
"""Test Petersen graph tree decomposition result"""
|
||||
G = nx.petersen_graph()
|
||||
_, decomp = treewidth_min_degree(G)
|
||||
is_tree_decomp(G, decomp)
|
||||
|
||||
def test_small_tree_treewidth(self):
|
||||
"""Test small tree
|
||||
|
||||
Test if the computed treewidth of the known self.small_tree is 2.
|
||||
As we know which value we can expect from our heuristic, values other
|
||||
than two are regressions
|
||||
"""
|
||||
G = self.small_tree
|
||||
# the order of removal should be [1,2,4]3[5,6,7]
|
||||
# (with [] denoting any order of the containing nodes)
|
||||
# resulting in treewidth 2 for the heuristic
|
||||
treewidth, _ = treewidth_min_fill_in(G)
|
||||
assert treewidth == 2
|
||||
|
||||
def test_heuristic_abort(self):
|
||||
"""Test heuristic abort condition for fully connected graph"""
|
||||
graph = {}
|
||||
for u in self.complete:
|
||||
graph[u] = set()
|
||||
for v in self.complete[u]:
|
||||
if u != v: # ignore self-loop
|
||||
graph[u].add(v)
|
||||
|
||||
deg_heuristic = MinDegreeHeuristic(graph)
|
||||
node = deg_heuristic.best_node(graph)
|
||||
if node is None:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_empty_graph(self):
|
||||
"""Test empty graph"""
|
||||
G = nx.Graph()
|
||||
_, _ = treewidth_min_degree(G)
|
||||
|
||||
def test_two_component_graph(self):
|
||||
"""Test empty graph"""
|
||||
G = nx.Graph()
|
||||
G.add_node(1)
|
||||
G.add_node(2)
|
||||
treewidth, _ = treewidth_min_degree(G)
|
||||
assert treewidth == 0
|
||||
|
||||
def test_heuristic_first_steps(self):
|
||||
"""Test first steps of min_degree heuristic"""
|
||||
graph = {
|
||||
n: set(self.deterministic_graph[n]) - {n} for n in self.deterministic_graph
|
||||
}
|
||||
deg_heuristic = MinDegreeHeuristic(graph)
|
||||
elim_node = deg_heuristic.best_node(graph)
|
||||
print(f"Graph {graph}:")
|
||||
steps = []
|
||||
|
||||
while elim_node is not None:
|
||||
print(f"Removing {elim_node}:")
|
||||
steps.append(elim_node)
|
||||
nbrs = graph[elim_node]
|
||||
|
||||
for u, v in itertools.permutations(nbrs, 2):
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
|
||||
for u in graph:
|
||||
if elim_node in graph[u]:
|
||||
graph[u].remove(elim_node)
|
||||
|
||||
del graph[elim_node]
|
||||
print(f"Graph {graph}:")
|
||||
elim_node = deg_heuristic.best_node(graph)
|
||||
|
||||
# check only the first 5 elements for equality
|
||||
assert steps[:5] == [0, 1, 2, 3, 4]
|
||||
|
||||
|
||||
class TestTreewidthMinFillIn:
|
||||
"""Unit tests for the treewidth_min_fill_in function."""
|
||||
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
"""Setup for different kinds of trees"""
|
||||
cls.complete = nx.Graph()
|
||||
cls.complete.add_edge(1, 2)
|
||||
cls.complete.add_edge(2, 3)
|
||||
cls.complete.add_edge(1, 3)
|
||||
|
||||
cls.small_tree = nx.Graph()
|
||||
cls.small_tree.add_edge(1, 2)
|
||||
cls.small_tree.add_edge(2, 3)
|
||||
cls.small_tree.add_edge(3, 4)
|
||||
cls.small_tree.add_edge(1, 4)
|
||||
cls.small_tree.add_edge(2, 4)
|
||||
cls.small_tree.add_edge(4, 5)
|
||||
cls.small_tree.add_edge(5, 6)
|
||||
cls.small_tree.add_edge(5, 7)
|
||||
cls.small_tree.add_edge(6, 7)
|
||||
|
||||
cls.deterministic_graph = nx.Graph()
|
||||
cls.deterministic_graph.add_edge(1, 2)
|
||||
cls.deterministic_graph.add_edge(1, 3)
|
||||
cls.deterministic_graph.add_edge(3, 4)
|
||||
cls.deterministic_graph.add_edge(2, 4)
|
||||
cls.deterministic_graph.add_edge(3, 5)
|
||||
cls.deterministic_graph.add_edge(4, 5)
|
||||
cls.deterministic_graph.add_edge(3, 6)
|
||||
cls.deterministic_graph.add_edge(5, 6)
|
||||
|
||||
def test_petersen_graph(self):
|
||||
"""Test Petersen graph tree decomposition result"""
|
||||
G = nx.petersen_graph()
|
||||
_, decomp = treewidth_min_fill_in(G)
|
||||
is_tree_decomp(G, decomp)
|
||||
|
||||
def test_small_tree_treewidth(self):
|
||||
"""Test if the computed treewidth of the known self.small_tree is 2"""
|
||||
G = self.small_tree
|
||||
# the order of removal should be [1,2,4]3[5,6,7]
|
||||
# (with [] denoting any order of the containing nodes)
|
||||
# resulting in treewidth 2 for the heuristic
|
||||
treewidth, _ = treewidth_min_fill_in(G)
|
||||
assert treewidth == 2
|
||||
|
||||
def test_heuristic_abort(self):
|
||||
"""Test if min_fill_in returns None for fully connected graph"""
|
||||
graph = {}
|
||||
for u in self.complete:
|
||||
graph[u] = set()
|
||||
for v in self.complete[u]:
|
||||
if u != v: # ignore self-loop
|
||||
graph[u].add(v)
|
||||
next_node = min_fill_in_heuristic(graph)
|
||||
if next_node is None:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
def test_empty_graph(self):
|
||||
"""Test empty graph"""
|
||||
G = nx.Graph()
|
||||
_, _ = treewidth_min_fill_in(G)
|
||||
|
||||
def test_two_component_graph(self):
|
||||
"""Test empty graph"""
|
||||
G = nx.Graph()
|
||||
G.add_node(1)
|
||||
G.add_node(2)
|
||||
treewidth, _ = treewidth_min_fill_in(G)
|
||||
assert treewidth == 0
|
||||
|
||||
def test_heuristic_first_steps(self):
|
||||
"""Test first steps of min_fill_in heuristic"""
|
||||
graph = {
|
||||
n: set(self.deterministic_graph[n]) - {n} for n in self.deterministic_graph
|
||||
}
|
||||
print(f"Graph {graph}:")
|
||||
elim_node = min_fill_in_heuristic(graph)
|
||||
steps = []
|
||||
|
||||
while elim_node is not None:
|
||||
print(f"Removing {elim_node}:")
|
||||
steps.append(elim_node)
|
||||
nbrs = graph[elim_node]
|
||||
|
||||
for u, v in itertools.permutations(nbrs, 2):
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
|
||||
for u in graph:
|
||||
if elim_node in graph[u]:
|
||||
graph[u].remove(elim_node)
|
||||
|
||||
del graph[elim_node]
|
||||
print(f"Graph {graph}:")
|
||||
elim_node = min_fill_in_heuristic(graph)
|
||||
|
||||
# check only the first 2 elements for equality
|
||||
assert steps[:2] == [6, 5]
|
|
@ -0,0 +1,55 @@
|
|||
import networkx as nx
|
||||
from networkx.algorithms.approximation import min_weighted_vertex_cover
|
||||
|
||||
|
||||
def is_cover(G, node_cover):
|
||||
return all({u, v} & node_cover for u, v in G.edges())
|
||||
|
||||
|
||||
class TestMWVC:
|
||||
"""Unit tests for the approximate minimum weighted vertex cover
|
||||
function,
|
||||
:func:`~networkx.algorithms.approximation.vertex_cover.min_weighted_vertex_cover`.
|
||||
|
||||
"""
|
||||
|
||||
def test_unweighted_directed(self):
|
||||
# Create a star graph in which half the nodes are directed in
|
||||
# and half are directed out.
|
||||
G = nx.DiGraph()
|
||||
G.add_edges_from((0, v) for v in range(1, 26))
|
||||
G.add_edges_from((v, 0) for v in range(26, 51))
|
||||
cover = min_weighted_vertex_cover(G)
|
||||
assert 2 == len(cover)
|
||||
assert is_cover(G, cover)
|
||||
|
||||
def test_unweighted_undirected(self):
|
||||
# create a simple star graph
|
||||
size = 50
|
||||
sg = nx.star_graph(size)
|
||||
cover = min_weighted_vertex_cover(sg)
|
||||
assert 2 == len(cover)
|
||||
assert is_cover(sg, cover)
|
||||
|
||||
def test_weighted(self):
|
||||
wg = nx.Graph()
|
||||
wg.add_node(0, weight=10)
|
||||
wg.add_node(1, weight=1)
|
||||
wg.add_node(2, weight=1)
|
||||
wg.add_node(3, weight=1)
|
||||
wg.add_node(4, weight=1)
|
||||
|
||||
wg.add_edge(0, 1)
|
||||
wg.add_edge(0, 2)
|
||||
wg.add_edge(0, 3)
|
||||
wg.add_edge(0, 4)
|
||||
|
||||
wg.add_edge(1, 2)
|
||||
wg.add_edge(2, 3)
|
||||
wg.add_edge(3, 4)
|
||||
wg.add_edge(4, 1)
|
||||
|
||||
cover = min_weighted_vertex_cover(wg, weight="weight")
|
||||
csum = sum(wg.nodes[node]["weight"] for node in cover)
|
||||
assert 4 == csum
|
||||
assert is_cover(wg, cover)
|
Loading…
Add table
Add a link
Reference in a new issue