def test_plot_prop(): num_nodes = 50 net = ng.erdos_renyi(nodes=num_nodes, avg_deg=5) net.set_weights(distribution="gaussian", parameters={"avg": 5, "std": 0.5}) net.new_node_attribute("attr", "int", values=np.random.randint(-10, 20, num_nodes)) nplt.degree_distribution(net, ["in", "out", "total"], show=False) nplt.edge_attributes_distribution(net, "weight", colors="g", show=False) nplt.node_attributes_distribution(net, "out-degree", colors="r", show=False) if nngt.get_config("backend") != "nngt": nplt.edge_attributes_distribution(net, ["betweenness", "weight"], colors=["g", "b"], axtitles=["Edge betw.", "Weights"], show=False) nplt.node_attributes_distribution( net, ["betweenness", "attr", "out-degree"], colors=["r", "g", "b"], show=False)
def test_binary_undirected_clustering(): ''' Check that directed local clustering returns undirected value if graph is not directed. ''' # pre-defined graph num_nodes = 5 edge_list = [(0, 3), (1, 0), (1, 2), (2, 4), (4, 1), (4, 3), (4, 2), (4, 0)] # expected results loc_clst = [2 / 3., 2 / 3., 1., 1., 0.5] glob_clst = 0.6428571428571429 # create graph g = nngt.Graph(nodes=num_nodes) g.new_edges(edge_list) # check all 3 ways of computing the local clustering assert np.all( np.isclose(na.local_clustering_binary_undirected(g), loc_clst)) assert np.all(np.isclose(na.local_clustering(g, directed=False), loc_clst)) assert np.all( np.isclose(nngt.analyze_graph["local_clustering"](g, directed=False), loc_clst)) # check all 4 ways of computing the global clustering assert np.isclose(na.global_clustering(g, directed=False), glob_clst) assert np.isclose(na.transitivity(g, directed=False), glob_clst) assert np.isclose(na.global_clustering_binary_undirected(g), glob_clst) assert np.isclose( nngt.analyze_graph["global_clustering"](g, directed=False), glob_clst) # check that self-loops are ignore g.new_edge(0, 0, self_loop=True) assert np.all( np.isclose(na.local_clustering_binary_undirected(g), loc_clst)) assert np.isclose(na.global_clustering_binary_undirected(g), glob_clst) # sanity check for local clustering on undirected unweighted graph g = ng.erdos_renyi(avg_deg=10, nodes=100, directed=False) ccu = na.local_clustering_binary_undirected(g) cc = na.local_clustering(g) assert np.all(np.isclose(cc, ccu))
def test_total_undirected_connectivities(): ''' Test total-degree connectivities ''' num_nodes = 1000 # erdos-renyi density = 0.1 lower, upper = 0.3, 5.4 weights = {"distribution": "uniform", "lower": lower, "upper": upper} g = ng.erdos_renyi(density=density, nodes=num_nodes, directed=False, weights=weights) assert g.edge_nb() / (num_nodes * num_nodes) == density # check weights ww = g.get_weights() assert np.all((lower <= ww) * (ww <= upper)) # check other graph types for directed in (True, False): # fixed-degree deg = 50 g = ng.fixed_degree(deg, "total", nodes=num_nodes, directed=directed) assert {deg} == set(g.get_degrees()) # gaussian degree avg = 50. std = 5. g = ng.gaussian_degree(avg, std, degree_type="total", nodes=num_nodes, directed=directed) deviation = 20. / np.sqrt(num_nodes) average = np.average(g.get_degrees()) assert avg - deviation <= average <= avg + deviation
def test_set_weights(): w = 10. g = ng.erdos_renyi(nodes=100, density=0.1, weights=w) assert set(g.get_weights()) == {w} w2 = 5. g.set_weights(w2) assert set(g.get_weights()) == {w2} elist = g.get_edges()[:10] # keep 10 first edges w3 = 2. g.set_weights(w3, elist=elist) assert set(g.get_weights()) == {w2, w3} assert set(g.get_weights(edges=elist)) == {w3}
def test_weighted_undirected_clustering(): ''' Check relevant properties of weighted clustering: * give back the binary definition if all weights are one * corner cases for specific networks, see [Saramaki2007] * equivalence between no edge and zero-weight edge for 'continuous' method Note: onnela and barrat are already check against networkx and igraph implementations in libarry_compatibility.py ''' g = ng.erdos_renyi(avg_deg=10, nodes=100, directed=False) # recover binary ccb = na.local_clustering_binary_undirected(g) for method in methods: ccw = na.local_clustering(g, weights='weight', method=method) assert np.all(np.isclose(ccb, ccw)) # corner cases eps = 1e-15 # 3 nodes num_nodes = 3 edge_list = [(0, 1), (1, 2), (2, 0)] # all epsilon weights = [eps, eps, eps] g = nngt.Graph(nodes=num_nodes, directed=False) g.new_edges(edge_list, attributes={"weight": weights}) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) assert np.array_equal(cc, [1, 1, 1]) # one weight is one g.set_weights(np.array([eps, eps, 1])) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == "barrat": assert np.all(np.isclose(cc, 1)) elif method == "zhang": assert np.all(np.isclose(cc, [0, 1, 0])) else: assert np.all(np.isclose(cc, 0, atol=1e-4)) # two weights are one g.set_weights(np.array([eps, 1, 1])) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == "barrat": assert np.all(np.isclose(cc, 1)) elif method == "zhang": # due to floating point rounding errors, we get 0.9 instead of 1 assert np.all(np.isclose(cc, (0.9, 0.9, 0), atol=1e-3)) else: assert np.all(np.isclose(cc, 0, atol=1e-2)) # 4 nodes num_nodes = 4 edge_list = [(0, 1), (1, 2), (2, 0), (2, 3)] g = nngt.Graph(nodes=num_nodes, directed=False) g.new_edges(edge_list) # out of triangle edge is epsilon g.set_weights([1, 1, 1, eps]) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == 'barrat': assert np.all(np.isclose(cc, [1, 1, 0.5, 0])) elif method in ("continuous", "zhang"): assert np.all(np.isclose(cc, [1, 1, 1, 0])) else: assert np.all(np.isclose(cc, [1, 1, 1 / 3, 0])) # out of triangle edge is 1 others are epsilon g.set_weights([eps, eps, eps, 1]) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == 'barrat': assert np.all(np.isclose(cc, [1, 1, 0, 0])) else: assert np.all(np.isclose(cc, 0)) # opposite triangle edge is 1 others are epsilon g.set_weights([1, eps, eps, eps]) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == 'barrat': assert np.all(np.isclose(cc, [1, 1, 1 / 3, 0])) elif method == "zhang": assert np.all(np.isclose(cc, [0, 0, 1 / 3, 0])) else: assert np.all(np.isclose(cc, 0, atol=1e-5)) # adjacent triangle edge is 1 others are epsilon g.set_weights([eps, 1, eps, eps]) for method in methods: cc = na.local_clustering(g, weights='weight', method=method) if method == 'barrat': assert np.all(np.isclose(cc, [1, 1, 1 / 2, 0])) elif method == "zhang": assert np.all(np.isclose(cc, [1, 0, 0, 0])) else: assert np.all(np.isclose(cc, 0, atol=1e-4)) # check zero-weight edge/no edge equivalence for continuous method num_nodes = 6 edge_list = [(0, 1), (1, 2), (2, 0), (2, 3), (4, 5)] g = nngt.Graph(nodes=num_nodes, directed=False) g.new_edges(edge_list) g.set_weights([1 / 64, 1 / 729, 1 / 64, 1 / 729, 1]) # triangle is 1/20736 # triplets are [1/64, 1/216, 62/5832, 0, 0, 0] expected = [1 / 324, 1 / 96, 9 / 1984, 0, 0, 0] cc = na.local_clustering(g, weights='weight', method='continuous') assert np.all(np.isclose(cc, expected)) # 0-weight case g.set_weights([1 / 64, 1 / 729, 1 / 64, 0, 1]) cc0 = na.local_clustering(g, weights='weight', method='continuous') # no-edge case edge_list = [(0, 1), (1, 2), (2, 0), (4, 5)] g = nngt.Graph(nodes=num_nodes, directed=False) g.new_edges(edge_list) g.set_weights([1 / 64, 1 / 729, 1 / 64, 1]) expected = [1 / 324, 1 / 96, 1 / 96, 0, 0, 0] ccn = na.local_clustering(g, weights='weight', method='continuous') assert np.all(np.isclose(cc0, ccn)) assert np.all(np.isclose(cc0, expected))
import nngt import nngt.generation as ng # np.random.seed(0) # ------------------- # # Generate the graphs # # ------------------- # num_nodes = 1000 avg_deg_er = 25 avg_deg_sf = 100 # random graphs g1 = ng.erdos_renyi(nodes=num_nodes, avg_deg=avg_deg_er) # the same graph but undirected g2 = ng.erdos_renyi(nodes=num_nodes, avg_deg=avg_deg_er, directed=False) # 2-step generation of a scale-free with Gaussian weight distribution w = {"distribution": "gaussian", "avg": 60., "std": 5.} g3 = nngt.Graph(num_nodes, weights=w) ng.random_scale_free(2.2, 2.9, avg_deg=avg_deg_sf, from_graph=g3) # same in 1 step g4 = ng.random_scale_free(2.2, 2.9, avg_deg=avg_deg_sf, nodes=num_nodes,
print(g3.edge_attributes['rank'], '\n') # check default values e = g3.new_edge(99, 98) g3.new_edges(np.random.randint(50, 100, (5, 2)), ignore_invalid=True) print(g3.edge_attributes['rank'], '\n') ''' ---------------------------------------- # # Generate and analyze more complex networks # # ---------------------------------------- ''' from nngt import generation as ng from nngt import analysis as na from nngt import plot as nplt # make an ER network g = ng.erdos_renyi(nodes=1000, avg_deg=100) if nngt.get_config("with_plot"): nplt.degree_distribution(g, ('in', 'total'), show=False) print("Clustering ER: {}".format(na.global_clustering(g))) # then a scale-free network g = ng.random_scale_free(1.8, 3.2, nodes=1000, avg_deg=100) if nngt.get_config("with_plot"): nplt.degree_distribution(g, ('in', 'out'), num_bins=30, logx=True, logy=True, show=True)
def test_graph_copy(): ''' Test partial and full graph copy. ''' # partial copy # non-spatial graph avg = 20 std = 4 g = ng.gaussian_degree(avg, std, nodes=100) h = nngt.Graph(copy_graph=g) assert g.node_nb() == h.node_nb() assert g.edge_nb() == h.edge_nb() assert np.array_equal(g.edges_array, h.edges_array) # spatial network pop = nngt.NeuralPop.exc_and_inhib(100) shape = nngt.geometry.Shape.rectangle(1000., 1000.) g = ng.gaussian_degree(avg, std, population=pop, shape=shape, name="new_node_spatial") h = nngt.Graph(copy_graph=g) assert g.node_nb() == h.node_nb() assert g.edge_nb() == h.edge_nb() assert np.array_equal(g.edges_array, h.edges_array) assert not h.is_network() assert not h.is_spatial() # full copy rng = np.random.default_rng() g.set_weights(rng.uniform(0, 10, g.edge_nb())) g.new_node_attribute("plop", "int", rng.integers(1, 50, g.node_nb())) g.new_node_attribute("bip", "double", rng.uniform(0, 1, g.node_nb())) g.new_edge_attribute("test", "int", rng.integers(1, 200, g.edge_nb())) copy = g.copy() assert g.node_nb() == copy.node_nb() assert g.edge_nb() == copy.edge_nb() assert np.array_equal(g.edges_array, copy.edges_array) for k, v in g.edge_attributes.items(): npt.assert_array_equal(v, copy.edge_attributes[k]) for k, v in g.node_attributes.items(): npt.assert_array_equal(v, copy.node_attributes[k]) assert g.population == copy.population assert g.population is not copy.population assert g.shape == copy.shape assert g.shape is not copy.shape # check that undirected graph stays undirected g = ng.erdos_renyi(nodes=100, avg_deg=10, directed=False) h = g.copy() assert g.is_directed() == h.is_directed() == False # eid is protected and should not be copied to a visible edge attribute assert "eid" not in h.edge_attributes