|
| 1 | +import math |
| 2 | + |
| 3 | +import pytest |
| 4 | +import reticula as ret |
| 5 | +from hypothesis import given |
| 6 | +from network_strategies import undirected_network, directed_network |
| 7 | + |
| 8 | + |
| 9 | +def test_density(): |
| 10 | + g = ret.complete_graph[ret.int64](size=4) |
| 11 | + assert ret.density(g) == 1.0 |
| 12 | + |
| 13 | + g = ret.undirected_network[ret.int64](edges=[], verts=range(4)) |
| 14 | + assert ret.density(g) == 0.0 |
| 15 | + |
| 16 | + g = ret.path_graph[ret.int64](size=4) |
| 17 | + expected_density = 3 / 6 |
| 18 | + assert ret.density(g) == pytest.approx(expected_density) |
| 19 | + |
| 20 | + |
| 21 | +def test_is_connected(): |
| 22 | + g = ret.path_graph[ret.int64](size=4) |
| 23 | + assert ret.is_connected(g) |
| 24 | + |
| 25 | + g = ret.undirected_network[ret.int64]([(0, 1), (2, 3)]) |
| 26 | + assert not ret.is_connected(g) |
| 27 | + |
| 28 | + g = ret.undirected_network[ret.int64]([], [0]) |
| 29 | + assert ret.is_connected(g) |
| 30 | + |
| 31 | + g = ret.undirected_network[ret.int64]() |
| 32 | + assert ret.is_connected(g) |
| 33 | + |
| 34 | + |
| 35 | +def test_is_weakly_connected(): |
| 36 | + g = ret.directed_network[ret.int64]([(0, 1), (1, 2)]) |
| 37 | + assert ret.is_weakly_connected(g) |
| 38 | + |
| 39 | + g = ret.directed_network[ret.int64]([(0, 1), (2, 3)]) |
| 40 | + assert not ret.is_weakly_connected(g) |
| 41 | + |
| 42 | + |
| 43 | +def test_is_acyclic(): |
| 44 | + g = ret.directed_network[ret.int64]([(0, 1), (0, 2), (1, 3), (2, 3)]) |
| 45 | + assert ret.is_acyclic(g) |
| 46 | + |
| 47 | + g = ret.directed_network[ret.int64]([(0, 1), (1, 2), (2, 0)]) |
| 48 | + assert not ret.is_acyclic(g) |
| 49 | + |
| 50 | + |
| 51 | +def test_topological_order(): |
| 52 | + g = ret.directed_network[ret.int64]([(0, 1), (0, 2), (1, 3), (2, 3)]) |
| 53 | + order = ret.topological_order(g) |
| 54 | + assert len(order) == 4 |
| 55 | + assert order.index(0) < order.index(1) |
| 56 | + assert order.index(0) < order.index(2) |
| 57 | + assert order.index(1) < order.index(3) |
| 58 | + assert order.index(2) < order.index(3) |
| 59 | + |
| 60 | + g = ret.directed_network[ret.int64]([(0, 1), (1, 2), (2, 0)]) |
| 61 | + pytest.raises(ValueError, ret.topological_order, g) |
| 62 | + |
| 63 | + |
| 64 | +def test_shortest_path_lengths(): |
| 65 | + g = ret.path_graph[ret.int64](size=4) |
| 66 | + |
| 67 | + distances_from = ret.shortest_path_lengths_from(g, 0) |
| 68 | + assert distances_from[0] == 0 |
| 69 | + assert distances_from[1] == 1 |
| 70 | + assert distances_from[2] == 2 |
| 71 | + assert distances_from[3] == 3 |
| 72 | + assert ret.shortest_path_lengths_from(g, 12) == {12: 0} |
| 73 | + |
| 74 | + distances_to = ret.shortest_path_lengths_to(g, 3) |
| 75 | + assert distances_to[0] == 3 |
| 76 | + assert distances_to[1] == 2 |
| 77 | + assert distances_to[2] == 1 |
| 78 | + assert distances_to[3] == 0 |
| 79 | + assert ret.shortest_path_lengths_to(g, 12) == {12: 0} |
| 80 | + |
| 81 | + |
| 82 | +def test_is_reachable(): |
| 83 | + g = ret.path_graph[ret.int64](size=4) |
| 84 | + assert ret.is_reachable(g, 0, 3) |
| 85 | + assert ret.is_reachable(g, 3, 0) |
| 86 | + |
| 87 | + g = ret.undirected_network[ret.int64]([(0, 1), (2, 3)]) |
| 88 | + assert not ret.is_reachable(g, 0, 2) |
| 89 | + |
| 90 | + |
| 91 | +def test_component_functions(): |
| 92 | + g = ret.undirected_network[ret.int64]([(0, 1), (2, 3), (4, 5), (5, 6)]) |
| 93 | + |
| 94 | + comp = ret.connected_component(g, 0) |
| 95 | + assert set(comp) == {0, 1} |
| 96 | + assert len(comp) == 2 |
| 97 | + |
| 98 | + comp = ret.largest_connected_component(g) |
| 99 | + assert set(comp) == {4, 5, 6} |
| 100 | + |
| 101 | + all_comps = ret.connected_components(g) |
| 102 | + assert len(all_comps) == 3 |
| 103 | + |
| 104 | + |
| 105 | +def test_weakly_connected_components(): |
| 106 | + g = ret.directed_network[ret.int64]([(0, 1), (2, 3)]) |
| 107 | + wccs = ret.weakly_connected_components(g) |
| 108 | + assert len(wccs) == 2 |
| 109 | + |
| 110 | + wcc_sets = [set(comp) for comp in wccs] |
| 111 | + assert {0, 1} in wcc_sets |
| 112 | + assert {2, 3} in wcc_sets |
| 113 | + |
| 114 | + lwcc = ret.largest_weakly_connected_component(g) |
| 115 | + assert len(lwcc) == 2 |
| 116 | + |
| 117 | + |
| 118 | +def test_in_out_components(): |
| 119 | + g = ret.directed_network[ret.int64]([(0, 1), (1, 2), (3, 1)]) |
| 120 | + |
| 121 | + in_comp = ret.in_component(g, 1) |
| 122 | + assert 0 in in_comp |
| 123 | + assert 3 in in_comp |
| 124 | + |
| 125 | + out_comp = ret.out_component(g, 1) |
| 126 | + assert 2 in out_comp |
| 127 | + |
| 128 | + in_sizes = ret.in_component_sizes(g) |
| 129 | + assert len(in_sizes) == len(g.vertices()) |
| 130 | + |
| 131 | + out_sizes = ret.out_component_sizes(g) |
| 132 | + assert len(out_sizes) == len(g.vertices()) |
| 133 | + |
| 134 | + |
| 135 | +def test_degree_sequence(): |
| 136 | + g = ret.undirected_network[ret.int64]([(0, 1), (1, 2), (2, 3)]) |
| 137 | + |
| 138 | + deg_seq = ret.degree_sequence(g) |
| 139 | + assert set(deg_seq) == {1, 2, 2, 1} |
| 140 | + |
| 141 | + g = ret.directed_network[ret.int64]([(0, 1), (0, 2), (1, 2)]) |
| 142 | + in_deg_seq = ret.in_degree_sequence(g) |
| 143 | + assert set(in_deg_seq) == {0, 1, 2} |
| 144 | + |
| 145 | + out_deg_seq = ret.out_degree_sequence(g) |
| 146 | + assert set(out_deg_seq) == {2, 1, 0} |
| 147 | + |
| 148 | + in_out_deg_seq = ret.in_out_degree_pair_sequence(g) |
| 149 | + assert set(in_out_deg_seq) == {(0, 2), (1, 1), (2, 0)} |
| 150 | + |
| 151 | + inc_deg_seq = ret.incident_degree_sequence(g) |
| 152 | + assert set(inc_deg_seq) == {2, 2, 2} |
| 153 | + |
| 154 | + |
| 155 | +@given(undirected_network()) |
| 156 | +def test_degree_properties(net): |
| 157 | + for v in net.vertices(): |
| 158 | + deg = ret.degree(net, v) |
| 159 | + assert deg >= 0 |
| 160 | + assert deg == len([e for e in net.edges() if v in e.incident_verts()]) |
| 161 | + |
| 162 | + |
| 163 | +@given(directed_network()) |
| 164 | +def test_directed_degree_properties(net): |
| 165 | + for v in net.vertices(): |
| 166 | + in_deg = ret.in_degree(net, v) |
| 167 | + out_deg = ret.out_degree(net, v) |
| 168 | + assert in_deg >= 0 |
| 169 | + assert out_deg >= 0 |
| 170 | + |
| 171 | + |
| 172 | +def test_attribute_assortativity(): |
| 173 | + g = ret.undirected_network[ret.int64]([(0, 1), (1, 2), (2, 3)]) |
| 174 | + attrs = {0: 1.0, 1: 2.0, 2: 2.0, 3: 1.0} |
| 175 | + |
| 176 | + r = ret.attribute_assortativity(g, attrs, 0.0) |
| 177 | + assert isinstance(r, float) |
| 178 | + assert r == pytest.approx(-0.5) |
| 179 | + |
| 180 | + r = ret.attribute_assortativity(g, {}, 1.0) |
| 181 | + assert math.isnan(r) |
0 commit comments