132 lines
3.8 KiB
Python
132 lines
3.8 KiB
Python
import easygraph as eg
|
|
import pytest
|
|
|
|
from easygraph.classes import operation
|
|
from easygraph.utils import edges_equal
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"graph_type", [eg.Graph, eg.DiGraph, eg.MultiGraph, eg.MultiDiGraph]
|
|
)
|
|
def test_selfloops(graph_type):
|
|
G = eg.complete_graph(3, create_using=graph_type)
|
|
G.add_edge(0, 0)
|
|
assert edges_equal(eg.selfloop_edges(G), [(0, 0)])
|
|
assert edges_equal(eg.selfloop_edges(G, data=True), [(0, 0, {})])
|
|
assert eg.number_of_selfloops(G) == 1
|
|
|
|
|
|
def test_set_edge_attributes_scalar():
|
|
G = eg.path_graph(3)
|
|
eg.set_edge_attributes(G, 5, "weight")
|
|
for _, _, data in G.edges:
|
|
assert data["weight"] == 5
|
|
|
|
|
|
def test_set_edge_attributes_dict():
|
|
G = eg.path_graph(3)
|
|
attrs = {(0, 1): 3, (1, 2): 7}
|
|
eg.set_edge_attributes(G, attrs, "weight")
|
|
assert G[0][1]["weight"] == 3
|
|
assert G[1][2]["weight"] == 7
|
|
|
|
|
|
def test_set_edge_attributes_dict_of_dict():
|
|
G = eg.path_graph(3)
|
|
attrs = {(0, 1): {"a": 1}, (1, 2): {"b": 2}}
|
|
eg.set_edge_attributes(G, attrs)
|
|
assert G[0][1]["a"] == 1
|
|
assert G[1][2]["b"] == 2
|
|
|
|
|
|
def test_set_node_attributes_scalar():
|
|
G = eg.path_graph(3)
|
|
eg.set_node_attributes(G, 42, "level")
|
|
for n in G.nodes:
|
|
assert G.nodes[n]["level"] == 42
|
|
|
|
|
|
def test_set_node_attributes_dict():
|
|
G = eg.path_graph(3)
|
|
eg.set_node_attributes(G, {0: "x", 1: "y"}, name="tag")
|
|
assert G.nodes[0]["tag"] == "x"
|
|
assert G.nodes[1]["tag"] == "y"
|
|
|
|
|
|
def test_set_node_attributes_dict_of_dict():
|
|
G = eg.path_graph(3)
|
|
eg.set_node_attributes(G, {0: {"foo": 10}, 1: {"bar": 20}})
|
|
assert G.nodes[0]["foo"] == 10
|
|
assert G.nodes[1]["bar"] == 20
|
|
|
|
|
|
def test_add_path_structure_and_attrs():
|
|
G = eg.Graph()
|
|
eg.add_path(G, [10, 11, 12], weight=9)
|
|
actual_edges = {(u, v) for u, v, _ in G.edges}
|
|
assert actual_edges == {(10, 11), (11, 12)}
|
|
assert G[10][11]["weight"] == 9
|
|
assert G[11][12]["weight"] == 9
|
|
|
|
|
|
def test_topological_sort_linear():
|
|
G = eg.DiGraph()
|
|
G.add_edges_from([(1, 2), (2, 3)])
|
|
assert list(operation.topological_sort(G)) == [1, 2, 3]
|
|
|
|
|
|
def test_topological_sort_cycle():
|
|
G = eg.DiGraph([(0, 1), (1, 2), (2, 0)])
|
|
with pytest.raises(AssertionError, match="contains a cycle"):
|
|
list(operation.topological_sort(G))
|
|
|
|
|
|
def test_selfloop_edges_variants():
|
|
G = eg.MultiGraph()
|
|
G.add_edge(0, 0, key="x", label="loop")
|
|
G.add_edge(1, 1, key="y", label="loop2")
|
|
basic = list(eg.selfloop_edges(G))
|
|
with_data = list(eg.selfloop_edges(G, data=True))
|
|
with_keys = list(eg.selfloop_edges(G, keys=True))
|
|
full = list(eg.selfloop_edges(G, keys=True, data="label"))
|
|
assert (0, 0) in basic and (1, 1) in basic
|
|
assert all(len(t) == 3 for t in with_data)
|
|
assert all(len(t) == 3 for t in with_keys)
|
|
assert "x" in [k for _, _, k, _ in full]
|
|
|
|
|
|
def test_number_of_selfloops():
|
|
G = eg.MultiGraph()
|
|
G.add_edges_from([(0, 0), (1, 1), (1, 2)])
|
|
assert eg.number_of_selfloops(G) == 2
|
|
|
|
|
|
def test_density_undirected():
|
|
G = eg.complete_graph(5)
|
|
d = eg.density(G)
|
|
assert pytest.approx(d, 0.01) == 1.0
|
|
|
|
|
|
def test_density_directed():
|
|
G = eg.DiGraph()
|
|
G.add_edges_from([(0, 1), (1, 2)])
|
|
d = eg.density(G)
|
|
assert pytest.approx(d, 0.01) == 2 / (3 * (3 - 1)) # 2/6
|
|
|
|
|
|
def test_topological_generations_linear():
|
|
G = eg.DiGraph()
|
|
G.add_edges_from([(1, 2), (2, 3), (3, 4)])
|
|
generations = list(operation.topological_generations(G))
|
|
assert generations == [[1], [2], [3], [4]]
|
|
|
|
|
|
def test_topological_generations_branching():
|
|
G = eg.DiGraph()
|
|
G.add_edges_from([(1, 2), (1, 3), (2, 4), (3, 4)])
|
|
generations = list(operation.topological_generations(G))
|
|
# Valid topological generations: [1], [2, 3], [4]
|
|
assert generations[0] == [1]
|
|
assert set(generations[1]) == {2, 3}
|
|
assert generations[2] == [4]
|