chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import unittest
|
||||
|
||||
import easygraph as eg
|
||||
|
||||
from easygraph import average_shortest_path_length
|
||||
from easygraph.utils.exception import EasyGraphError
|
||||
from easygraph.utils.exception import EasyGraphPointlessConcept
|
||||
|
||||
|
||||
class TestAverageShortestPathLength(unittest.TestCase):
|
||||
def test_unweighted_path_graph(self):
|
||||
G = eg.path_graph(5)
|
||||
result = average_shortest_path_length(G)
|
||||
self.assertEqual(result, 2.0)
|
||||
|
||||
def test_weighted_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_edge(0, 1, weight=1)
|
||||
G.add_edge(1, 2, weight=2)
|
||||
G.add_edge(2, 3, weight=3)
|
||||
result = average_shortest_path_length(G, weight="weight", method="dijkstra")
|
||||
self.assertAlmostEqual(result, 3.333, places=3)
|
||||
|
||||
def test_trivial_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_node(1)
|
||||
self.assertEqual(average_shortest_path_length(G), 0)
|
||||
|
||||
def test_disconnected_graph_undirected(self):
|
||||
G = eg.Graph([(1, 2), (3, 4)])
|
||||
with self.assertRaises(EasyGraphError):
|
||||
average_shortest_path_length(G)
|
||||
|
||||
def test_disconnected_graph_directed(self):
|
||||
G = eg.DiGraph([(0, 1), (2, 3)])
|
||||
with self.assertRaises(EasyGraphError):
|
||||
average_shortest_path_length(G)
|
||||
|
||||
def test_null_graph(self):
|
||||
G = eg.Graph()
|
||||
with self.assertRaises(EasyGraphPointlessConcept):
|
||||
average_shortest_path_length(G)
|
||||
|
||||
def test_directed_strongly_connected(self):
|
||||
G = eg.DiGraph([(0, 1), (1, 2), (2, 0)])
|
||||
result = average_shortest_path_length(G)
|
||||
self.assertEqual(result, 1.5)
|
||||
|
||||
def test_unsupported_method(self):
|
||||
G = eg.path_graph(5)
|
||||
with self.assertRaises(ValueError):
|
||||
average_shortest_path_length(G, method="unsupported_method")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,158 @@
|
||||
import unittest
|
||||
|
||||
import easygraph as eg
|
||||
|
||||
from easygraph.utils.exception import EasyGraphNotImplemented
|
||||
|
||||
|
||||
class test_bridges(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g1 = eg.get_graph_karateclub()
|
||||
|
||||
# source graph: https://zh.wikipedia.org/zh-cn/%E6%88%B4%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95#/media/File:Dijkstra_Animation.gif
|
||||
edges = [(1, 2), (1, 3), (1, 6), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)]
|
||||
self.g2 = eg.Graph(edges)
|
||||
self.g2.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 7},
|
||||
{"weight": 9},
|
||||
{"weight": 14},
|
||||
{"weight": 10},
|
||||
{"weight": 15},
|
||||
{"weight": 11},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 9},
|
||||
],
|
||||
)
|
||||
|
||||
# source graph: https://static.javatpoint.com/tutorial/daa/images/dijkstra-algorithm.png
|
||||
self.g3 = eg.Graph()
|
||||
edges = [
|
||||
(0, 1),
|
||||
(0, 4),
|
||||
(1, 4),
|
||||
(1, 2),
|
||||
(4, 5),
|
||||
(4, 8),
|
||||
(2, 3),
|
||||
(2, 6),
|
||||
(2, 8),
|
||||
(5, 6),
|
||||
(5, 8),
|
||||
(3, 6),
|
||||
(3, 7),
|
||||
(6, 7),
|
||||
]
|
||||
|
||||
self.g3.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 4},
|
||||
{"weight": 1},
|
||||
{"weight": 11},
|
||||
{"weight": 8},
|
||||
{"weight": 1},
|
||||
{"weight": 7},
|
||||
{"weight": 7},
|
||||
{"weight": 4},
|
||||
{"weight": 2},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 14},
|
||||
{"weight": 9},
|
||||
{"weight": 10},
|
||||
],
|
||||
)
|
||||
self.g4 = eg.Graph()
|
||||
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 2), (1, 3)]
|
||||
self.g4.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": -1},
|
||||
{"weight": -2},
|
||||
{"weight": -3},
|
||||
{"weight": -4},
|
||||
{"weight": -5},
|
||||
{"weight": -6},
|
||||
],
|
||||
)
|
||||
|
||||
def result(self, g: eg.Graph):
|
||||
res = eg.bridges(g)
|
||||
for i in res:
|
||||
print(i)
|
||||
|
||||
def test_bridges(self):
|
||||
self.result(g=self.g2)
|
||||
self.result(g=self.g3)
|
||||
self.result(g=self.g4)
|
||||
|
||||
def test_has_bridges(self):
|
||||
print(eg.has_bridges(self.g2))
|
||||
|
||||
def test_empty_graph(self):
|
||||
g = eg.Graph()
|
||||
self.assertFalse(eg.has_bridges(g))
|
||||
self.assertEqual(list(eg.bridges(g)), [])
|
||||
|
||||
def test_single_node_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_node(1)
|
||||
self.assertFalse(eg.has_bridges(g))
|
||||
self.assertEqual(list(eg.bridges(g)), [])
|
||||
|
||||
def test_disconnected_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges_from([(0, 1), (2, 3)])
|
||||
self.assertTrue(eg.has_bridges(g))
|
||||
self.assertCountEqual(list(eg.bridges(g)), [(0, 1), (2, 3)])
|
||||
|
||||
def test_cycle_graph(self):
|
||||
g = eg.DiGraph([(1, 2), (2, 3), (3, 1)])
|
||||
self.assertFalse(eg.has_bridges(g))
|
||||
self.assertEqual(list(eg.bridges(g)), [])
|
||||
|
||||
def test_path_graph(self):
|
||||
g = eg.path_graph(4)
|
||||
self.assertTrue(eg.has_bridges(g))
|
||||
self.assertCountEqual(list(eg.bridges(g)), [(0, 1), (1, 2), (2, 3)])
|
||||
|
||||
def test_star_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges_from([(0, i) for i in range(1, 5)])
|
||||
|
||||
expected = [(0, 1), (0, 2), (0, 3), (0, 4)]
|
||||
self.assertTrue(eg.has_bridges(g))
|
||||
self.assertCountEqual(list(eg.bridges(g)), expected)
|
||||
|
||||
def test_complete_graph(self):
|
||||
g = eg.complete_graph(5)
|
||||
self.assertFalse(eg.has_bridges(g))
|
||||
self.assertEqual(list(eg.bridges(g)), [])
|
||||
|
||||
def test_graph_with_invalid_root(self):
|
||||
g = eg.path_graph(3)
|
||||
with self.assertRaises(eg.NodeNotFound):
|
||||
list(eg.bridges(g, root=10))
|
||||
|
||||
def test_multigraph_exception(self):
|
||||
g = eg.MultiGraph()
|
||||
g.add_edges_from([(0, 1), (1, 2)])
|
||||
with self.assertRaises(EasyGraphNotImplemented):
|
||||
list(eg.bridges(g))
|
||||
with self.assertRaises(EasyGraphNotImplemented):
|
||||
eg.has_bridges(g)
|
||||
|
||||
def test_weighted_graph_should_ignore_weights(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges_from(
|
||||
[(0, 1), (1, 2), (2, 3), (3, 0)],
|
||||
edges_attr=[{"weight": 10}, {"weight": 20}, {"weight": 30}, {"weight": 40}],
|
||||
)
|
||||
self.assertFalse(eg.has_bridges(g))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,143 @@
|
||||
import unittest
|
||||
|
||||
import easygraph as eg
|
||||
|
||||
|
||||
class test_diameter(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g1 = eg.get_graph_karateclub()
|
||||
|
||||
# source graph: https://zh.wikipedia.org/zh-cn/%E6%88%B4%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95#/media/File:Dijkstra_Animation.gif
|
||||
edges = [(1, 2), (1, 3), (1, 6), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)]
|
||||
self.g2 = eg.Graph(edges)
|
||||
self.g2.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 7},
|
||||
{"weight": 9},
|
||||
{"weight": 14},
|
||||
{"weight": 10},
|
||||
{"weight": 15},
|
||||
{"weight": 11},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 9},
|
||||
],
|
||||
)
|
||||
|
||||
# source graph: https://static.javatpoint.com/tutorial/daa/images/dijkstra-algorithm.png
|
||||
self.g3 = eg.Graph()
|
||||
edges = [
|
||||
(0, 1),
|
||||
(0, 4),
|
||||
(1, 4),
|
||||
(1, 2),
|
||||
(4, 5),
|
||||
(4, 8),
|
||||
(2, 3),
|
||||
(2, 6),
|
||||
(2, 8),
|
||||
(5, 6),
|
||||
(5, 8),
|
||||
(3, 6),
|
||||
(3, 7),
|
||||
(6, 7),
|
||||
]
|
||||
|
||||
self.g3.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 4},
|
||||
{"weight": 1},
|
||||
{"weight": 11},
|
||||
{"weight": 8},
|
||||
{"weight": 1},
|
||||
{"weight": 7},
|
||||
{"weight": 7},
|
||||
{"weight": 4},
|
||||
{"weight": 2},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 14},
|
||||
{"weight": 9},
|
||||
{"weight": 10},
|
||||
],
|
||||
)
|
||||
self.g4 = eg.DiGraph()
|
||||
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 2), (1, 3), (1, 0)]
|
||||
self.g4.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 1},
|
||||
{"weight": 2},
|
||||
{"weight": 3},
|
||||
{"weight": 4},
|
||||
{"weight": 5},
|
||||
{"weight": 6},
|
||||
{"weight": 11},
|
||||
],
|
||||
)
|
||||
|
||||
def test_diameter(self):
|
||||
print(eg.diameter(self.g2))
|
||||
print(eg.diameter(self.g3))
|
||||
print(eg.diameter(self.g4))
|
||||
|
||||
def test_eccentricity(self):
|
||||
print(eg.eccentricity(self.g2, list(self.g2.nodes.keys())[0:-1]))
|
||||
print(eg.eccentricity(self.g3))
|
||||
print(eg.eccentricity(self.g4))
|
||||
|
||||
def test_single_node_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_node(1)
|
||||
self.assertEqual(eg.eccentricity(G), {1: 0})
|
||||
self.assertEqual(eg.diameter(G), 0)
|
||||
|
||||
def test_two_node_graph(self):
|
||||
G = eg.Graph([(1, 2)])
|
||||
self.assertEqual(eg.eccentricity(G), {1: 1, 2: 1})
|
||||
self.assertEqual(eg.diameter(G), 1)
|
||||
|
||||
def test_disconnected_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_nodes_from([1, 2, 3])
|
||||
G.add_edge(1, 2)
|
||||
with self.assertRaises(eg.EasyGraphError):
|
||||
eg.eccentricity(G)
|
||||
|
||||
def test_directed_not_strongly_connected(self):
|
||||
G = eg.DiGraph()
|
||||
G.add_edges_from([(1, 2), (2, 3)]) # Not strongly connected
|
||||
with self.assertRaises(eg.EasyGraphError):
|
||||
eg.eccentricity(G)
|
||||
|
||||
def test_eccentricity_with_sp(self):
|
||||
G = eg.Graph([(1, 2), (2, 3)])
|
||||
sp = {
|
||||
1: {1: 0, 2: 1, 3: 2},
|
||||
2: {2: 0, 1: 1, 3: 1},
|
||||
3: {3: 0, 2: 1, 1: 2},
|
||||
}
|
||||
self.assertEqual(eg.eccentricity(G, sp=sp), {1: 2, 2: 1, 3: 2})
|
||||
self.assertEqual(eg.diameter(G, e=eg.eccentricity(G, sp=sp)), 2)
|
||||
|
||||
def test_eccentricity_single_node_query(self):
|
||||
G = eg.Graph([(1, 2), (2, 3)])
|
||||
self.assertEqual(eg.eccentricity(G, v=1), 2)
|
||||
self.assertEqual(eg.eccentricity(G, v=2), 1)
|
||||
|
||||
def test_eccentricity_subset_of_nodes(self):
|
||||
G = eg.Graph([(1, 2), (2, 3)])
|
||||
result = eg.eccentricity(G, v=[1, 3])
|
||||
self.assertEqual(result[1], 2)
|
||||
self.assertEqual(result[3], 2)
|
||||
|
||||
def test_diameter_matches_max_eccentricity(self):
|
||||
G = eg.Graph([(1, 2), (2, 3)])
|
||||
ecc = eg.eccentricity(G)
|
||||
self.assertEqual(eg.diameter(G, e=ecc), max(ecc.values()))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,176 @@
|
||||
import unittest
|
||||
|
||||
import easygraph as eg
|
||||
|
||||
|
||||
class test_mst(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g1 = eg.get_graph_karateclub()
|
||||
|
||||
# source graph: https://zh.wikipedia.org/zh-cn/%E6%88%B4%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95#/media/File:Dijkstra_Animation.gif
|
||||
edges = [(1, 2), (1, 3), (1, 6), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)]
|
||||
self.g2 = eg.Graph(edges)
|
||||
self.g2.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 7},
|
||||
{"weight": 9},
|
||||
{"weight": 14},
|
||||
{"weight": 10},
|
||||
{"weight": 15},
|
||||
{"weight": 11},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 9},
|
||||
],
|
||||
)
|
||||
|
||||
# source graph: https://static.javatpoint.com/tutorial/daa/images/dijkstra-algorithm.png
|
||||
self.g3 = eg.Graph()
|
||||
edges = [
|
||||
(0, 1),
|
||||
(0, 4),
|
||||
(1, 4),
|
||||
(1, 2),
|
||||
(4, 5),
|
||||
(4, 8),
|
||||
(2, 3),
|
||||
(2, 6),
|
||||
(2, 8),
|
||||
(5, 6),
|
||||
(5, 8),
|
||||
(3, 6),
|
||||
(3, 7),
|
||||
(6, 7),
|
||||
]
|
||||
|
||||
self.g3.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 4},
|
||||
{"weight": 1},
|
||||
{"weight": 11},
|
||||
{"weight": 8},
|
||||
{"weight": 1},
|
||||
{"weight": 7},
|
||||
{"weight": 7},
|
||||
{"weight": 4},
|
||||
{"weight": 2},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 14},
|
||||
{"weight": 9},
|
||||
{"weight": 10},
|
||||
],
|
||||
)
|
||||
self.g4 = eg.DiGraph()
|
||||
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 2), (1, 3)]
|
||||
self.g4.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": -1},
|
||||
{"weight": -2},
|
||||
{"weight": -3},
|
||||
{"weight": -4},
|
||||
{"weight": -5},
|
||||
{"weight": -6},
|
||||
],
|
||||
)
|
||||
self.nan_graph = eg.Graph()
|
||||
self.nan_graph.add_edges(
|
||||
[(0, 1), (1, 2)], edges_attr=[{"weight": float("nan")}, {"weight": 1}]
|
||||
)
|
||||
|
||||
self.no_weight_graph = eg.Graph()
|
||||
self.no_weight_graph.add_edges([(0, 1), (1, 2)])
|
||||
|
||||
self.equal_weight_graph = eg.Graph()
|
||||
self.equal_weight_graph.add_edges(
|
||||
[(0, 1), (1, 2), (2, 0)],
|
||||
edges_attr=[{"weight": 1}, {"weight": 1}, {"weight": 1}],
|
||||
)
|
||||
|
||||
self.negative_weight_graph = eg.Graph()
|
||||
self.negative_weight_graph.add_edges(
|
||||
[(0, 1), (1, 2), (2, 3)],
|
||||
edges_attr=[{"weight": -1}, {"weight": -2}, {"weight": -3}],
|
||||
)
|
||||
|
||||
self.disconnected_graph = eg.Graph()
|
||||
self.disconnected_graph.add_edges(
|
||||
[(0, 1), (2, 3)], edges_attr=[{"weight": 1}, {"weight": 2}]
|
||||
)
|
||||
|
||||
self.G = eg.Graph()
|
||||
self.G.add_edges(
|
||||
[(0, 1), (1, 2), (2, 3), (3, 0)],
|
||||
edges_attr=[{"weight": 1}, {"weight": 2}, {"weight": 3}, {"weight": 4}],
|
||||
)
|
||||
|
||||
def helper(self, g: eg.Graph, func):
|
||||
result = func(g)
|
||||
if isinstance(result, eg.Graph):
|
||||
print("nodes: " + str(result.nodes))
|
||||
print("edges: " + str(result.edges))
|
||||
else:
|
||||
for i in result:
|
||||
print(i)
|
||||
|
||||
def test_minimum_spanning_edges(self):
|
||||
print("test_minimum_spanning_edges")
|
||||
self.helper(self.g2, eg.minimum_spanning_edges)
|
||||
self.helper(self.g2, eg.minimum_spanning_edges)
|
||||
self.helper(self.g4, eg.minimum_spanning_edges)
|
||||
|
||||
def test_maximum_spanning_edges(self):
|
||||
print("test_maximum_spanning_edges")
|
||||
self.helper(self.g2, eg.maximum_spanning_edges)
|
||||
self.helper(self.g2, eg.maximum_spanning_edges)
|
||||
self.helper(self.g4, eg.maximum_spanning_edges)
|
||||
|
||||
def test_minimum_spanning_tree(self):
|
||||
print("test_minimum_spanning_tree")
|
||||
self.helper(self.g2, eg.minimum_spanning_tree)
|
||||
self.helper(self.g2, eg.minimum_spanning_tree)
|
||||
self.helper(self.g4, eg.minimum_spanning_tree)
|
||||
|
||||
def test_maximum_spanning_tree(self):
|
||||
print("test_maximum_spanning_tree")
|
||||
self.helper(self.g2, eg.maximum_spanning_tree)
|
||||
self.helper(self.g2, eg.maximum_spanning_tree)
|
||||
self.helper(self.g4, eg.maximum_spanning_tree)
|
||||
|
||||
def test_nan_handling(self):
|
||||
with self.assertRaises(ValueError):
|
||||
list(eg.minimum_spanning_edges(self.nan_graph))
|
||||
edges = list(eg.minimum_spanning_edges(self.nan_graph, ignore_nan=True))
|
||||
self.assertEqual(len(edges), 1)
|
||||
|
||||
def test_missing_weight_defaults_to_one(self):
|
||||
edges = list(eg.minimum_spanning_edges(self.no_weight_graph))
|
||||
self.assertEqual(len(edges), 2)
|
||||
|
||||
def test_negative_weights(self):
|
||||
edges = list(eg.minimum_spanning_edges(self.negative_weight_graph))
|
||||
weights = [attr["weight"] for _, _, attr in edges]
|
||||
self.assertIn(-3, weights)
|
||||
self.assertEqual(len(edges), 3)
|
||||
|
||||
def test_disconnected_graph(self):
|
||||
edges = list(eg.minimum_spanning_edges(self.disconnected_graph))
|
||||
self.assertEqual(len(edges), 2)
|
||||
|
||||
def test_maximum_vs_minimum_edges(self):
|
||||
min_edges = list(eg.minimum_spanning_edges(self.G))
|
||||
max_edges = list(eg.maximum_spanning_edges(self.G))
|
||||
min_set = {(min(u, v), max(u, v)) for u, v, _ in min_edges}
|
||||
max_set = {(min(u, v), max(u, v)) for u, v, _ in max_edges}
|
||||
self.assertNotEqual(min_set, max_set)
|
||||
|
||||
def test_invalid_algorithm_name(self):
|
||||
with self.assertRaises(ValueError):
|
||||
list(eg.minimum_spanning_edges(self.G, algorithm="invalid_algo"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,200 @@
|
||||
import unittest
|
||||
|
||||
import easygraph as eg
|
||||
|
||||
|
||||
class test_path(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g1 = eg.get_graph_karateclub()
|
||||
|
||||
# source graph: https://zh.wikipedia.org/zh-cn/%E6%88%B4%E5%85%8B%E6%96%AF%E7%89%B9%E6%8B%89%E7%AE%97%E6%B3%95#/media/File:Dijkstra_Animation.gif
|
||||
edges = [(1, 2), (1, 3), (1, 6), (2, 3), (2, 4), (3, 4), (3, 6), (4, 5), (5, 6)]
|
||||
self.g2 = eg.Graph(edges)
|
||||
self.g2.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 7},
|
||||
{"weight": 9},
|
||||
{"weight": 14},
|
||||
{"weight": 10},
|
||||
{"weight": 15},
|
||||
{"weight": 11},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 9},
|
||||
],
|
||||
)
|
||||
|
||||
# source graph: https://static.javatpoint.com/tutorial/daa/images/dijkstra-algorithm.png
|
||||
self.g3 = eg.Graph()
|
||||
edges = [
|
||||
(0, 1),
|
||||
(0, 4),
|
||||
(1, 4),
|
||||
(1, 2),
|
||||
(4, 5),
|
||||
(4, 8),
|
||||
(2, 3),
|
||||
(2, 6),
|
||||
(2, 8),
|
||||
(5, 6),
|
||||
(5, 8),
|
||||
(3, 6),
|
||||
(3, 7),
|
||||
(6, 7),
|
||||
]
|
||||
|
||||
self.g3.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": 4},
|
||||
{"weight": 1},
|
||||
{"weight": 11},
|
||||
{"weight": 8},
|
||||
{"weight": 1},
|
||||
{"weight": 7},
|
||||
{"weight": 7},
|
||||
{"weight": 4},
|
||||
{"weight": 2},
|
||||
{"weight": 2},
|
||||
{"weight": 6},
|
||||
{"weight": 14},
|
||||
{"weight": 9},
|
||||
{"weight": 10},
|
||||
],
|
||||
)
|
||||
self.g4 = eg.Graph()
|
||||
edges = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 2), (1, 3)]
|
||||
self.g4.add_edges(
|
||||
edges,
|
||||
edges_attr=[
|
||||
{"weight": -1},
|
||||
{"weight": -2},
|
||||
{"weight": -3},
|
||||
{"weight": -4},
|
||||
{"weight": -5},
|
||||
{"weight": -6},
|
||||
],
|
||||
)
|
||||
|
||||
def test_Dijkstra(self):
|
||||
print("Dijkstra tested:")
|
||||
print(eg.Dijkstra(self.g2, node=1))
|
||||
print(eg.Dijkstra(self.g3, node=0))
|
||||
print()
|
||||
|
||||
def test_Floyd(self):
|
||||
print("Floyd tested:")
|
||||
print(eg.Floyd(self.g2))
|
||||
print(eg.Floyd(self.g3))
|
||||
print(eg.Floyd(self.g4))
|
||||
# probably need a negative circle detection for input graphs
|
||||
print()
|
||||
|
||||
def test_Prim(self):
|
||||
print("Prim tested:")
|
||||
print(eg.Prim(self.g2))
|
||||
print(eg.Prim(self.g3))
|
||||
print(eg.Prim(self.g4))
|
||||
print()
|
||||
|
||||
def test_Kruskal(self):
|
||||
print("Krusal tested:")
|
||||
print(eg.Kruskal(self.g2))
|
||||
print(eg.Kruskal(self.g3))
|
||||
print(eg.Kruskal(self.g4))
|
||||
print()
|
||||
|
||||
def test_Spfa(self):
|
||||
try:
|
||||
print(eg.Spfa(self.g2, 1))
|
||||
except eg.EasyGraphError as e:
|
||||
print(e)
|
||||
|
||||
def test_single_source_bfs(self):
|
||||
print("single_source_bfs tested:")
|
||||
print(eg.single_source_bfs(self.g2, 1, target=5))
|
||||
print(eg.single_source_bfs(self.g3, 0, target=6))
|
||||
print(eg.single_source_bfs(self.g4, 0, target=3))
|
||||
print()
|
||||
|
||||
def test_single_source_dijkstra(self):
|
||||
# identical to Dijkstra method
|
||||
pass
|
||||
|
||||
def test_multi_source_dijkstra(self):
|
||||
print("multi_source_dijkstra tested")
|
||||
print(eg.multi_source_dijkstra(self.g2, sources=list(self.g2.nodes.keys())))
|
||||
print(eg.multi_source_dijkstra(self.g3, sources=list(self.g2.nodes.keys())))
|
||||
try:
|
||||
print(eg.multi_source_dijkstra(self.g4, sources=list(self.g2.nodes.keys())))
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
print()
|
||||
|
||||
def test_dijkstra_negative_weights_raises(self):
|
||||
with self.assertRaises(ValueError):
|
||||
eg.Dijkstra(self.g4, node=0)
|
||||
|
||||
def test_dijkstra_disconnected_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges([(1, 2)], edges_attr=[{"weight": 3}])
|
||||
g.add_node(3) # disconnected
|
||||
result = eg.Dijkstra(g, node=1)
|
||||
self.assertIn(3, g.nodes)
|
||||
self.assertNotIn(3, result)
|
||||
|
||||
def test_floyd_disconnected_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges([(1, 2)], edges_attr=[{"weight": 3}])
|
||||
g.add_node(3)
|
||||
result = eg.Floyd(g)
|
||||
self.assertEqual(result[1][3], float("inf"))
|
||||
self.assertEqual(result[3][3], 0)
|
||||
|
||||
def test_prim_disconnected_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges([(0, 1), (2, 3)], edges_attr=[{"weight": 1}, {"weight": 1}])
|
||||
result = eg.Prim(g)
|
||||
count = sum(len(v) for v in result.values())
|
||||
self.assertLess(
|
||||
count, len(g.nodes) - 1
|
||||
) # not enough edges to connect all nodes
|
||||
|
||||
def test_kruskal_disconnected_graph(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges([(0, 1), (2, 3)], edges_attr=[{"weight": 1}, {"weight": 1}])
|
||||
result = eg.Kruskal(g)
|
||||
count = sum(len(v) for v in result.values())
|
||||
self.assertLess(count, len(g.nodes) - 1)
|
||||
|
||||
def test_spfa_always_errors(self):
|
||||
with self.assertRaises(eg.EasyGraphError):
|
||||
eg.Spfa(self.g2, 0)
|
||||
|
||||
def test_single_source_bfs_no_target(self):
|
||||
result = eg.single_source_bfs(self.g2, 1)
|
||||
self.assertIn(0, result.values()) # BFS level exists
|
||||
self.assertIsInstance(result, dict)
|
||||
|
||||
def test_single_source_bfs_target_not_found(self):
|
||||
g = eg.Graph()
|
||||
g.add_edges([(1, 2)], edges_attr=[{"weight": 1}])
|
||||
g.add_node(99)
|
||||
result = eg.single_source_bfs(g, 1, target=99)
|
||||
self.assertNotIn(99, result)
|
||||
|
||||
def test_multi_source_dijkstra_empty_sources(self):
|
||||
result = eg.multi_source_dijkstra(self.g2, sources=[])
|
||||
self.assertEqual(result, {})
|
||||
|
||||
def test_multi_source_dijkstra_matches_single(self):
|
||||
sources = [1, 2]
|
||||
multi = eg.multi_source_dijkstra(self.g2, sources)
|
||||
for s in sources:
|
||||
single = eg.single_source_dijkstra(self.g2, s)
|
||||
self.assertEqual(multi[s], single)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user