123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- import math
- import random
- from itertools import combinations
- import pytest
- import networkx as nx
- def l1dist(x, y):
- return sum(abs(a - b) for a, b in zip(x, y))
- class TestRandomGeometricGraph:
- """Unit tests for the :func:`~networkx.random_geometric_graph`
- function.
- """
- def test_number_of_nodes(self):
- G = nx.random_geometric_graph(50, 0.25, seed=42)
- assert len(G) == 50
- G = nx.random_geometric_graph(range(50), 0.25, seed=42)
- assert len(G) == 50
- def test_distances(self):
- """Tests that pairs of vertices adjacent if and only if they are
- within the prescribed radius.
- """
- # Use the Euclidean metric, the default according to the
- # documentation.
- G = nx.random_geometric_graph(50, 0.25)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- # Nonadjacent vertices must be at greater distance.
- else:
- assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_p(self):
- """Tests for providing an alternate distance metric to the
- generator.
- """
- # Use the L1 metric.
- G = nx.random_geometric_graph(50, 0.25, p=1)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- # Nonadjacent vertices must be at greater distance.
- else:
- assert not l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_node_names(self):
- """Tests using values other than sequential numbers as node IDs."""
- import string
- nodes = list(string.ascii_lowercase)
- G = nx.random_geometric_graph(nodes, 0.25)
- assert len(G) == len(nodes)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- # Nonadjacent vertices must be at greater distance.
- else:
- assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- class TestSoftRandomGeometricGraph:
- """Unit tests for the :func:`~networkx.soft_random_geometric_graph`
- function.
- """
- def test_number_of_nodes(self):
- G = nx.soft_random_geometric_graph(50, 0.25, seed=42)
- assert len(G) == 50
- G = nx.soft_random_geometric_graph(range(50), 0.25, seed=42)
- assert len(G) == 50
- def test_distances(self):
- """Tests that pairs of vertices adjacent if and only if they are
- within the prescribed radius.
- """
- # Use the Euclidean metric, the default according to the
- # documentation.
- G = nx.soft_random_geometric_graph(50, 0.25)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_p(self):
- """Tests for providing an alternate distance metric to the
- generator.
- """
- # Use the L1 metric.
- def dist(x, y):
- return sum(abs(a - b) for a, b in zip(x, y))
- G = nx.soft_random_geometric_graph(50, 0.25, p=1)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_node_names(self):
- """Tests using values other than sequential numbers as node IDs."""
- import string
- nodes = list(string.ascii_lowercase)
- G = nx.soft_random_geometric_graph(nodes, 0.25)
- assert len(G) == len(nodes)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_p_dist_default(self):
- """Tests default p_dict = 0.5 returns graph with edge count <= RGG with
- same n, radius, dim and positions
- """
- nodes = 50
- dim = 2
- pos = {v: [random.random() for i in range(dim)] for v in range(nodes)}
- RGG = nx.random_geometric_graph(50, 0.25, pos=pos)
- SRGG = nx.soft_random_geometric_graph(50, 0.25, pos=pos)
- assert len(SRGG.edges()) <= len(RGG.edges())
- def test_p_dist_zero(self):
- """Tests if p_dict = 0 returns disconnected graph with 0 edges"""
- def p_dist(dist):
- return 0
- G = nx.soft_random_geometric_graph(50, 0.25, p_dist=p_dist)
- assert len(G.edges) == 0
- def join(G, u, v, theta, alpha, metric):
- """Returns ``True`` if and only if the nodes whose attributes are
- ``du`` and ``dv`` should be joined, according to the threshold
- condition for geographical threshold graphs.
- ``G`` is an undirected NetworkX graph, and ``u`` and ``v`` are nodes
- in that graph. The nodes must have node attributes ``'pos'`` and
- ``'weight'``.
- ``metric`` is a distance metric.
- """
- du, dv = G.nodes[u], G.nodes[v]
- u_pos, v_pos = du["pos"], dv["pos"]
- u_weight, v_weight = du["weight"], dv["weight"]
- return (u_weight + v_weight) * metric(u_pos, v_pos) ** alpha >= theta
- class TestGeographicalThresholdGraph:
- """Unit tests for the :func:`~networkx.geographical_threshold_graph`
- function.
- """
- def test_number_of_nodes(self):
- G = nx.geographical_threshold_graph(50, 100, seed=42)
- assert len(G) == 50
- G = nx.geographical_threshold_graph(range(50), 100, seed=42)
- assert len(G) == 50
- def test_distances(self):
- """Tests that pairs of vertices adjacent if and only if their
- distances meet the given threshold.
- """
- # Use the Euclidean metric and alpha = -2
- # the default according to the documentation.
- G = nx.geographical_threshold_graph(50, 10)
- for u, v in combinations(G, 2):
- # Adjacent vertices must exceed the threshold.
- if v in G[u]:
- assert join(G, u, v, 10, -2, math.dist)
- # Nonadjacent vertices must not exceed the threshold.
- else:
- assert not join(G, u, v, 10, -2, math.dist)
- def test_metric(self):
- """Tests for providing an alternate distance metric to the
- generator.
- """
- # Use the L1 metric.
- G = nx.geographical_threshold_graph(50, 10, metric=l1dist)
- for u, v in combinations(G, 2):
- # Adjacent vertices must exceed the threshold.
- if v in G[u]:
- assert join(G, u, v, 10, -2, l1dist)
- # Nonadjacent vertices must not exceed the threshold.
- else:
- assert not join(G, u, v, 10, -2, l1dist)
- def test_p_dist_zero(self):
- """Tests if p_dict = 0 returns disconnected graph with 0 edges"""
- def p_dist(dist):
- return 0
- G = nx.geographical_threshold_graph(50, 1, p_dist=p_dist)
- assert len(G.edges) == 0
- class TestWaxmanGraph:
- """Unit tests for the :func:`~networkx.waxman_graph` function."""
- def test_number_of_nodes_1(self):
- G = nx.waxman_graph(50, 0.5, 0.1, seed=42)
- assert len(G) == 50
- G = nx.waxman_graph(range(50), 0.5, 0.1, seed=42)
- assert len(G) == 50
- def test_number_of_nodes_2(self):
- G = nx.waxman_graph(50, 0.5, 0.1, L=1)
- assert len(G) == 50
- G = nx.waxman_graph(range(50), 0.5, 0.1, L=1)
- assert len(G) == 50
- def test_metric(self):
- """Tests for providing an alternate distance metric to the
- generator.
- """
- # Use the L1 metric.
- G = nx.waxman_graph(50, 0.5, 0.1, metric=l1dist)
- assert len(G) == 50
- class TestNavigableSmallWorldGraph:
- def test_navigable_small_world(self):
- G = nx.navigable_small_world_graph(5, p=1, q=0, seed=42)
- gg = nx.grid_2d_graph(5, 5).to_directed()
- assert nx.is_isomorphic(G, gg)
- G = nx.navigable_small_world_graph(5, p=1, q=0, dim=3)
- gg = nx.grid_graph([5, 5, 5]).to_directed()
- assert nx.is_isomorphic(G, gg)
- G = nx.navigable_small_world_graph(5, p=1, q=0, dim=1)
- gg = nx.grid_graph([5]).to_directed()
- assert nx.is_isomorphic(G, gg)
- class TestThresholdedRandomGeometricGraph:
- """Unit tests for the :func:`~networkx.thresholded_random_geometric_graph`
- function.
- """
- def test_number_of_nodes(self):
- G = nx.thresholded_random_geometric_graph(50, 0.2, 0.1, seed=42)
- assert len(G) == 50
- G = nx.thresholded_random_geometric_graph(range(50), 0.2, 0.1)
- assert len(G) == 50
- def test_distances(self):
- """Tests that pairs of vertices adjacent if and only if they are
- within the prescribed radius.
- """
- # Use the Euclidean metric, the default according to the
- # documentation.
- G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_p(self):
- """Tests for providing an alternate distance metric to the
- generator.
- """
- # Use the L1 metric.
- def dist(x, y):
- return sum(abs(a - b) for a, b in zip(x, y))
- G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1, p=1)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_node_names(self):
- """Tests using values other than sequential numbers as node IDs."""
- import string
- nodes = list(string.ascii_lowercase)
- G = nx.thresholded_random_geometric_graph(nodes, 0.25, 0.1)
- assert len(G) == len(nodes)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
- def test_theta(self):
- """Tests that pairs of vertices adjacent if and only if their sum
- weights exceeds the threshold parameter theta.
- """
- G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1)
- for u, v in combinations(G, 2):
- # Adjacent vertices must be within the given distance.
- if v in G[u]:
- assert (G.nodes[u]["weight"] + G.nodes[v]["weight"]) >= 0.1
- def test_geometric_edges_raises_no_pos():
- G = nx.path_graph(3)
- msg = "All nodes in `G` must have a 'pos' attribute"
- with pytest.raises(nx.NetworkXError, match=msg):
- nx.geometric_edges(G, radius=1)
|