chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import easygraph as eg
|
||||
import pytest
|
||||
|
||||
from easygraph.functions.basic import average_degree
|
||||
|
||||
|
||||
def test_average_degree_basic():
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
assert average_degree(G) == pytest.approx(4 / 3)
|
||||
|
||||
|
||||
def test_average_degree_empty_graph():
|
||||
G = eg.Graph()
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
average_degree(G)
|
||||
|
||||
|
||||
def test_average_degree_self_loop():
|
||||
G = eg.Graph()
|
||||
G.add_edge(1, 1) # self-loop
|
||||
# Self-loop counts as 2 towards degree of node 1
|
||||
assert average_degree(G) == pytest.approx(2.0)
|
||||
|
||||
|
||||
def test_average_degree_with_isolated_node():
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(1, 2), (2, 3)])
|
||||
G.add_node(4) # isolated node
|
||||
assert average_degree(G) == pytest.approx(1.0)
|
||||
|
||||
|
||||
def test_average_degree_directed_graph():
|
||||
G = eg.DiGraph()
|
||||
G.add_edges_from([(1, 2), (2, 3), (3, 1)])
|
||||
assert average_degree(G) == pytest.approx(2.0)
|
||||
|
||||
|
||||
def test_average_degree_invalid_input():
|
||||
with pytest.raises(AttributeError):
|
||||
average_degree(None)
|
||||
@@ -0,0 +1,418 @@
|
||||
import easygraph as eg
|
||||
import pytest
|
||||
|
||||
|
||||
class TestClustering:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
pytest.importorskip("numpy")
|
||||
|
||||
def test_clustering(self):
|
||||
G = eg.DiGraph()
|
||||
G.add_edge("1", "2", weight=16)
|
||||
G.add_edge("2", "3", weight=16)
|
||||
G.add_edge("4", "3", weight=16)
|
||||
G.add_edge("3", "4", weight=23)
|
||||
G.add_edge("3", "5", weight=16)
|
||||
G.add_edge("4", "2", weight=20)
|
||||
print("clustering" in dir(eg))
|
||||
assert eg.clustering(G) == {
|
||||
"1": 0,
|
||||
"2": 0.3333333333333333,
|
||||
"3": 0.2,
|
||||
"4": 0.5,
|
||||
"5": 0,
|
||||
}
|
||||
|
||||
def test_path(self):
|
||||
G = eg.path_graph(10)
|
||||
assert list(eg.clustering(G).values()) == [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
assert eg.clustering(G) == {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
8: 0,
|
||||
9: 0,
|
||||
}
|
||||
|
||||
def test_k5(self):
|
||||
G = eg.complete_graph(5)
|
||||
assert list(eg.clustering(G).values()) == [1, 1, 1, 1, 1]
|
||||
assert eg.average_clustering(G) == 1
|
||||
G.remove_edge(1, 2)
|
||||
assert list(eg.clustering(G).values()) == [
|
||||
5 / 6,
|
||||
1,
|
||||
1,
|
||||
5 / 6,
|
||||
5 / 6,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4]) == {1: 1, 4: 0.83333333333333337}
|
||||
|
||||
def test_k5_signed(self):
|
||||
G = eg.complete_graph(5)
|
||||
assert list(eg.clustering(G).values()) == [1, 1, 1, 1, 1]
|
||||
assert eg.average_clustering(G) == 1
|
||||
G.remove_edge(1, 2)
|
||||
G.add_edge(0, 1, weight=-1)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
1 / 6,
|
||||
-1 / 3,
|
||||
1,
|
||||
3 / 6,
|
||||
3 / 6,
|
||||
]
|
||||
|
||||
|
||||
class TestDirectedClustering:
|
||||
def test_clustering(self):
|
||||
G = eg.DiGraph()
|
||||
assert list(eg.clustering(G).values()) == []
|
||||
assert eg.clustering(G) == {}
|
||||
|
||||
def test_path(self):
|
||||
G = eg.path_graph(10, create_using=eg.DiGraph())
|
||||
assert list(eg.clustering(G).values()) == [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
assert eg.clustering(G) == {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
8: 0,
|
||||
9: 0,
|
||||
}
|
||||
assert eg.clustering(G, 0) == 0
|
||||
|
||||
def test_k5(self):
|
||||
G = eg.complete_graph(5, create_using=eg.DiGraph())
|
||||
assert list(eg.clustering(G).values()) == [1, 1, 1, 1, 1]
|
||||
assert eg.average_clustering(G) == 1
|
||||
G.remove_edge(1, 2)
|
||||
assert list(eg.clustering(G).values()) == [
|
||||
11 / 12,
|
||||
1,
|
||||
1,
|
||||
11 / 12,
|
||||
11 / 12,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4]) == {1: 1, 4: 11 / 12}
|
||||
G.remove_edge(2, 1)
|
||||
assert list(eg.clustering(G).values()) == [
|
||||
5 / 6,
|
||||
1,
|
||||
1,
|
||||
5 / 6,
|
||||
5 / 6,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4]) == {1: 1, 4: 0.83333333333333337}
|
||||
assert eg.clustering(G, 4) == 5 / 6
|
||||
|
||||
def test_triangle_and_edge(self):
|
||||
G = eg.empty_graph(range(3), eg.DiGraph())
|
||||
G.add_edges_from(eg.pairwise(range(3), cyclic=True))
|
||||
G.add_edge(0, 4)
|
||||
assert eg.clustering(G)[0] == 1 / 6
|
||||
|
||||
|
||||
class TestDirectedAverageClustering:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
pytest.importorskip("numpy")
|
||||
|
||||
def test_empty(self):
|
||||
G = eg.DiGraph()
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
eg.average_clustering(G)
|
||||
|
||||
def test_average_clustering(self):
|
||||
G = eg.empty_graph(range(3), eg.DiGraph())
|
||||
G.add_edges_from(eg.pairwise(range(3), cyclic=True))
|
||||
G.add_edge(2, 3)
|
||||
assert eg.average_clustering(G) == (1 + 1 + 1 / 3) / 8
|
||||
assert eg.average_clustering(G, count_zeros=True) == (1 + 1 + 1 / 3) / 8
|
||||
assert eg.average_clustering(G, count_zeros=False) == (1 + 1 + 1 / 3) / 6
|
||||
assert eg.average_clustering(G, [1, 2, 3]) == (1 + 1 / 3) / 6
|
||||
assert eg.average_clustering(G, [1, 2, 3], count_zeros=True) == (1 + 1 / 3) / 6
|
||||
assert eg.average_clustering(G, [1, 2, 3], count_zeros=False) == (1 + 1 / 3) / 4
|
||||
|
||||
|
||||
class TestAverageClustering:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
pytest.importorskip("numpy")
|
||||
|
||||
def test_empty(self):
|
||||
G = eg.Graph()
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
eg.average_clustering(G)
|
||||
|
||||
def test_average_clustering(self):
|
||||
G = eg.complete_graph(3)
|
||||
G.add_edge(2, 3)
|
||||
|
||||
assert eg.average_clustering(G) == (1 + 1 + 1 / 3) / 4
|
||||
assert eg.average_clustering(G, count_zeros=True) == (1 + 1 + 1 / 3) / 4
|
||||
assert eg.average_clustering(G, count_zeros=False) == (1 + 1 + 1 / 3) / 3
|
||||
assert eg.average_clustering(G, [1, 2, 3]) == (1 + 1 / 3) / 3
|
||||
assert eg.average_clustering(G, [1, 2, 3], count_zeros=True) == (1 + 1 / 3) / 3
|
||||
assert eg.average_clustering(G, [1, 2, 3], count_zeros=False) == (1 + 1 / 3) / 2
|
||||
|
||||
def test_average_clustering_signed(self):
|
||||
G = eg.complete_graph(3)
|
||||
G.add_edge(2, 3)
|
||||
G.add_edge(0, 1, weight=-1)
|
||||
assert eg.average_clustering(G, weight="weight") == (-1 - 1 - 1 / 3) / 4
|
||||
assert (
|
||||
eg.average_clustering(G, weight="weight", count_zeros=True)
|
||||
== (-1 - 1 - 1 / 3) / 4
|
||||
)
|
||||
assert (
|
||||
eg.average_clustering(G, weight="weight", count_zeros=False)
|
||||
== (-1 - 1 - 1 / 3) / 3
|
||||
)
|
||||
|
||||
|
||||
class TestDirectedWeightedClustering:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
global np
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
def test_clustering(self):
|
||||
G = eg.DiGraph()
|
||||
assert list(eg.clustering(G, weight="weight").values()) == []
|
||||
assert eg.clustering(G) == {}
|
||||
|
||||
def test_path(self):
|
||||
G = eg.path_graph(10, create_using=eg.DiGraph())
|
||||
print("type:", eg.clustering(G, weight="weight"))
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
assert eg.clustering(G, weight="weight") == {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
8: 0,
|
||||
9: 0,
|
||||
}
|
||||
|
||||
def test_k5(self):
|
||||
G = eg.complete_graph(5, create_using=eg.DiGraph())
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [1, 1, 1, 1, 1]
|
||||
assert eg.average_clustering(G, weight="weight") == 1
|
||||
G.remove_edge(1, 2)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
11 / 12,
|
||||
1,
|
||||
1,
|
||||
11 / 12,
|
||||
11 / 12,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4], weight="weight") == {1: 1, 4: 11 / 12}
|
||||
G.remove_edge(2, 1)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
5 / 6,
|
||||
1,
|
||||
1,
|
||||
5 / 6,
|
||||
5 / 6,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4], weight="weight") == {
|
||||
1: 1,
|
||||
4: 0.83333333333333337,
|
||||
}
|
||||
|
||||
def test_triangle_and_edge(self):
|
||||
G = eg.empty_graph(range(3), create_using=eg.DiGraph())
|
||||
G.add_edges_from(eg.pairwise(range(3), cyclic=True))
|
||||
G.add_edge(0, 4, weight=2)
|
||||
assert eg.clustering(G)[0] == 1 / 6
|
||||
# Relaxed comparisons to allow graphblas-algorithms to pass tests
|
||||
np.testing.assert_allclose(eg.clustering(G, weight="weight")[0], 1 / 12)
|
||||
np.testing.assert_allclose(eg.clustering(G, 0, weight="weight"), 1 / 12)
|
||||
|
||||
|
||||
class TestWeightedClustering:
|
||||
@classmethod
|
||||
def setup_class(cls):
|
||||
global np
|
||||
np = pytest.importorskip("numpy")
|
||||
|
||||
def test_clustering(self):
|
||||
G = eg.Graph()
|
||||
assert list(eg.clustering(G, weight="weight").values()) == []
|
||||
assert eg.clustering(G) == {}
|
||||
|
||||
def test_path(self):
|
||||
G = eg.path_graph(10)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
assert eg.clustering(G, weight="weight") == {
|
||||
0: 0,
|
||||
1: 0,
|
||||
2: 0,
|
||||
3: 0,
|
||||
4: 0,
|
||||
5: 0,
|
||||
6: 0,
|
||||
7: 0,
|
||||
8: 0,
|
||||
9: 0,
|
||||
}
|
||||
|
||||
def test_cubical(self):
|
||||
G = eg.from_dict_of_lists(
|
||||
{
|
||||
0: [1, 3, 4],
|
||||
1: [0, 2, 7],
|
||||
2: [1, 3, 6],
|
||||
3: [0, 2, 5],
|
||||
4: [0, 5, 7],
|
||||
5: [3, 4, 6],
|
||||
6: [2, 5, 7],
|
||||
7: [1, 4, 6],
|
||||
},
|
||||
create_using=None,
|
||||
)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
assert eg.clustering(G, 1) == 0
|
||||
assert list(eg.clustering(G, [1, 2], weight="weight").values()) == [0, 0]
|
||||
assert eg.clustering(G, 1, weight="weight") == 0
|
||||
assert eg.clustering(G, [1, 2], weight="weight") == {1: 0, 2: 0}
|
||||
|
||||
def test_k5(self):
|
||||
G = eg.complete_graph(5)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [1, 1, 1, 1, 1]
|
||||
assert eg.average_clustering(G, weight="weight") == 1
|
||||
G.remove_edge(1, 2)
|
||||
assert list(eg.clustering(G, weight="weight").values()) == [
|
||||
5 / 6,
|
||||
1,
|
||||
1,
|
||||
5 / 6,
|
||||
5 / 6,
|
||||
]
|
||||
assert eg.clustering(G, [1, 4], weight="weight") == {
|
||||
1: 1,
|
||||
4: 0.83333333333333337,
|
||||
}
|
||||
|
||||
def test_triangle_and_edge(self):
|
||||
G = eg.empty_graph(range(3), None)
|
||||
G.add_edges_from(eg.pairwise(range(3), cyclic=True))
|
||||
G.add_edge(0, 4, weight=2)
|
||||
assert eg.clustering(G)[0] == 1 / 3
|
||||
np.testing.assert_allclose(eg.clustering(G, weight="weight")[0], 1 / 6)
|
||||
np.testing.assert_allclose(eg.clustering(G, 0, weight="weight"), 1 / 6)
|
||||
|
||||
def test_triangle_and_signed_edge(self):
|
||||
G = eg.empty_graph(range(3), None)
|
||||
G.add_edges_from(eg.pairwise(range(3), cyclic=True))
|
||||
G.add_edge(0, 1, weight=-1)
|
||||
G.add_edge(3, 0, weight=0)
|
||||
assert eg.clustering(G)[0] == 1 / 3
|
||||
assert eg.clustering(G, weight="weight")[0] == -1 / 3
|
||||
|
||||
|
||||
class TestAdditionalClusteringCases:
|
||||
def test_self_loops_ignored(self):
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (2, 0)])
|
||||
G.add_edge(0, 0) # self-loop
|
||||
assert eg.clustering(G, 0) == 1.0
|
||||
|
||||
def test_isolated_node(self):
|
||||
G = eg.Graph()
|
||||
G.add_node(1)
|
||||
assert eg.clustering(G) == {1: 0}
|
||||
|
||||
def test_degree_one_node(self):
|
||||
G = eg.Graph()
|
||||
G.add_edge(1, 2)
|
||||
assert eg.clustering(G) == {1: 0, 2: 0}
|
||||
|
||||
def test_custom_weight_name(self):
|
||||
G = eg.Graph()
|
||||
G.add_edge(0, 1, strength=2)
|
||||
G.add_edge(1, 2, strength=2)
|
||||
G.add_edge(2, 0, strength=2)
|
||||
result = eg.clustering(G, weight="strength")
|
||||
assert result[0] > 0
|
||||
|
||||
def test_negative_weights_mixed(self):
|
||||
G = eg.complete_graph(3)
|
||||
G[0][1]["weight"] = -1
|
||||
G[1][2]["weight"] = 1
|
||||
G[2][0]["weight"] = 1
|
||||
assert eg.clustering(G, 0, weight="weight") < 0
|
||||
|
||||
def test_directed_reciprocal_edges(self):
|
||||
G = eg.DiGraph()
|
||||
G.add_edges_from([(0, 1), (1, 0), (0, 2), (2, 0), (1, 2), (2, 1)])
|
||||
result = eg.clustering(G)
|
||||
assert all(0 <= v <= 1 for v in result.values())
|
||||
@@ -0,0 +1,104 @@
|
||||
import sys
|
||||
|
||||
import easygraph as eg
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from easygraph.functions.basic.localassort import localAssort
|
||||
|
||||
|
||||
class TestLocalAssort:
|
||||
@classmethod
|
||||
def setup_class(self):
|
||||
self.G = eg.get_graph_karateclub()
|
||||
edgelist = []
|
||||
node_num = len(self.G.nodes)
|
||||
for e in self.G.edges:
|
||||
edgelist.append([e[0] - 1, e[1] - 1])
|
||||
self.edgelist = np.int32(edgelist)
|
||||
self.valuelist = np.arange(node_num, dtype=np.int32) % 6
|
||||
|
||||
@pytest.mark.skipif(
|
||||
sys.version_info.major <= 3 and sys.version_info.minor <= 7,
|
||||
reason="python version should higher than 3.7",
|
||||
)
|
||||
def test_karateclub(self):
|
||||
assortM, assortT, Z = eg.localAssort(
|
||||
self.edgelist, self.valuelist, pr=np.arange(0, 1, 0.1)
|
||||
)
|
||||
|
||||
_, assortT, Z = eg.functions.basic.localassort.localAssort(
|
||||
self.edgelist, self.valuelist, pr=np.array([0.9])
|
||||
)
|
||||
|
||||
|
||||
def test_localassort_small_complete_graph():
|
||||
G = eg.complete_graph(4)
|
||||
edgelist = np.array(list(G.edges))
|
||||
node_attr = np.array([0, 0, 1, 1])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr)
|
||||
assert assortM.shape == (4, 10)
|
||||
assert assortT.shape == (4,)
|
||||
assert Z.shape == (4,)
|
||||
assert np.all(Z >= 0) and np.all(Z <= 1)
|
||||
|
||||
|
||||
def test_localassort_with_missing_attributes():
|
||||
G = eg.path_graph(5)
|
||||
edgelist = np.array(list(G.edges))
|
||||
node_attr = np.array([0, -1, 1, -1, 1])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr, pr=np.array([0.5]))
|
||||
assert assortT.shape == (5,)
|
||||
assert Z.shape == (5,)
|
||||
assert np.any(np.isnan(assortT))
|
||||
|
||||
|
||||
def test_localassort_directed_graph():
|
||||
G = eg.DiGraph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (2, 3)])
|
||||
edgelist = np.array(list(G.edges))
|
||||
node_attr = np.array([0, 1, 0, 1])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr, undir=False)
|
||||
assert assortM.shape == (4, 10)
|
||||
assert assortT.shape == (4,)
|
||||
assert Z.shape == (4,)
|
||||
|
||||
|
||||
def test_localassort_single_node_graph():
|
||||
edgelist = np.empty((0, 2), dtype=int)
|
||||
node_attr = np.array([0])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr)
|
||||
assert assortM.shape == (1, 10)
|
||||
assert np.all(np.isnan(assortM)) or np.allclose(assortM, 0, atol=1e-5)
|
||||
assert np.all(np.isnan(assortT)) or np.allclose(assortT, 0, atol=1e-5)
|
||||
assert np.all(np.isnan(Z)) or np.allclose(Z, 0, atol=1e-5)
|
||||
|
||||
|
||||
def test_localassort_disconnected_graph():
|
||||
G = eg.Graph()
|
||||
G.add_nodes_from(range(5))
|
||||
edgelist = np.empty((0, 2), dtype=int)
|
||||
node_attr = np.array([0, 1, 0, 1, 1])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr)
|
||||
assert assortM.shape == (5, 10)
|
||||
assert np.all(np.isnan(assortM)) or np.allclose(assortM, 0, atol=1e-5)
|
||||
assert np.all(np.isnan(assortT)) or np.allclose(assortT, 0, atol=1e-5)
|
||||
assert np.all(np.isnan(Z)) or np.allclose(Z, 0, atol=1e-5)
|
||||
|
||||
|
||||
def test_localassort_high_restart_probabilities():
|
||||
G = eg.path_graph(5)
|
||||
edgelist = np.array(list(G.edges))
|
||||
node_attr = np.array([1, 0, 1, 0, 1])
|
||||
pr = np.array([0.95, 0.99])
|
||||
assortM, assortT, Z = localAssort(edgelist, node_attr, pr=pr)
|
||||
assert assortM.shape == (5, 2)
|
||||
assert assortT.shape == (5,)
|
||||
assert Z.shape == (5,)
|
||||
|
||||
|
||||
def test_localassort_invalid_attribute_length():
|
||||
edgelist = np.array([[0, 1], [1, 2]])
|
||||
node_attr = np.array([0, 1]) # too short
|
||||
with pytest.raises(ValueError):
|
||||
localAssort(edgelist, node_attr)
|
||||
@@ -0,0 +1,79 @@
|
||||
import easygraph as eg
|
||||
import pytest
|
||||
|
||||
|
||||
class TestPredecessor:
|
||||
# @classmethod
|
||||
# def setup_class(self):
|
||||
# pytest.importskip("numpy")
|
||||
|
||||
def test_predecessor(self):
|
||||
G = eg.path_graph(4)
|
||||
for source in G:
|
||||
assert eg.predecessor(G, source) in [
|
||||
{0: [], 1: [0], 2: [1], 3: [2]},
|
||||
{1: [], 0: [1], 2: [1], 3: [2]},
|
||||
{2: [], 1: [2], 3: [2], 0: [1]},
|
||||
{3: [], 2: [3], 1: [2], 0: [1]},
|
||||
]
|
||||
|
||||
def test_basic_predecessor(self):
|
||||
G = eg.path_graph(4)
|
||||
result = eg.predecessor(G, 0)
|
||||
assert result == {0: [], 1: [0], 2: [1], 3: [2]}
|
||||
|
||||
def test_with_return_seen(self):
|
||||
G = eg.path_graph(4)
|
||||
pred, seen = eg.predecessor(G, 0, return_seen=True)
|
||||
assert pred == {0: [], 1: [0], 2: [1], 3: [2]}
|
||||
assert seen == {0: 0, 1: 1, 2: 2, 3: 3}
|
||||
|
||||
def test_with_target(self):
|
||||
G = eg.path_graph(4)
|
||||
assert eg.predecessor(G, 0, target=2) == [1]
|
||||
|
||||
def test_with_target_and_return_seen(self):
|
||||
G = eg.path_graph(4)
|
||||
pred, seen = eg.predecessor(G, 0, target=2, return_seen=True)
|
||||
assert pred == [1]
|
||||
assert seen == 2
|
||||
|
||||
def test_with_cutoff(self):
|
||||
G = eg.path_graph(4)
|
||||
pred = eg.predecessor(G, 0, cutoff=1)
|
||||
assert pred == {0: [], 1: [0]}
|
||||
|
||||
def test_disconnected_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(0, 1), (2, 3)])
|
||||
pred = eg.predecessor(G, 0)
|
||||
assert 2 not in pred and 3 not in pred
|
||||
|
||||
def test_invalid_source(self):
|
||||
G = eg.path_graph(4)
|
||||
with pytest.raises(eg.NodeNotFound):
|
||||
eg.predecessor(G, 99)
|
||||
|
||||
def test_no_path_to_target(self):
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(0, 1), (2, 3)])
|
||||
assert eg.predecessor(G, 0, target=3) == []
|
||||
|
||||
def test_no_path_to_target_with_return_seen(self):
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(0, 1), (2, 3)])
|
||||
pred, seen = eg.predecessor(G, 0, target=3, return_seen=True)
|
||||
assert pred == []
|
||||
assert seen == -1
|
||||
|
||||
def test_cycle_graph(self):
|
||||
G = eg.Graph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 0)]) # cycled graph
|
||||
pred = eg.predecessor(G, 0)
|
||||
assert set(pred.keys()) == set(G.nodes)
|
||||
|
||||
def test_directed_graph(self):
|
||||
G = eg.DiGraph()
|
||||
G.add_edges_from([(0, 1), (1, 2), (2, 3)])
|
||||
pred = eg.predecessor(G, 0)
|
||||
assert pred == {0: [], 1: [0], 2: [1], 3: [2]}
|
||||
Reference in New Issue
Block a user