365 lines
14 KiB
Python
365 lines
14 KiB
Python
|
#!/usr/bin/env python
|
||
|
import networkx as nx
|
||
|
from networkx.algorithms import bipartite
|
||
|
from networkx.testing import assert_edges_equal, assert_nodes_equal
|
||
|
|
||
|
|
||
|
class TestBipartiteProject:
|
||
|
|
||
|
def test_path_projected_graph(self):
|
||
|
G = nx.path_graph(4)
|
||
|
P = bipartite.projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
P = bipartite.projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
|
||
|
def test_path_projected_properties_graph(self):
|
||
|
G = nx.path_graph(4)
|
||
|
G.add_node(1, name='one')
|
||
|
G.add_node(2, name='two')
|
||
|
P = bipartite.projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
assert P.nodes[1]['name'] == G.nodes[1]['name']
|
||
|
P = bipartite.projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
assert P.nodes[2]['name'] == G.nodes[2]['name']
|
||
|
|
||
|
def test_path_collaboration_projected_graph(self):
|
||
|
G = nx.path_graph(4)
|
||
|
P = bipartite.collaboration_weighted_projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
P[1][3]['weight'] = 1
|
||
|
P = bipartite.collaboration_weighted_projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
P[0][2]['weight'] = 1
|
||
|
|
||
|
def test_directed_path_collaboration_projected_graph(self):
|
||
|
G = nx.DiGraph()
|
||
|
nx.add_path(G, range(4))
|
||
|
P = bipartite.collaboration_weighted_projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
P[1][3]['weight'] = 1
|
||
|
P = bipartite.collaboration_weighted_projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
P[0][2]['weight'] = 1
|
||
|
|
||
|
def test_path_weighted_projected_graph(self):
|
||
|
G = nx.path_graph(4)
|
||
|
P = bipartite.weighted_projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
P[1][3]['weight'] = 1
|
||
|
P = bipartite.weighted_projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
P[0][2]['weight'] = 1
|
||
|
|
||
|
def test_path_weighted_projected_directed_graph(self):
|
||
|
G = nx.DiGraph()
|
||
|
nx.add_path(G, range(4))
|
||
|
P = bipartite.weighted_projected_graph(G, [1, 3])
|
||
|
assert_nodes_equal(list(P), [1, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 3)])
|
||
|
P[1][3]['weight'] = 1
|
||
|
P = bipartite.weighted_projected_graph(G, [0, 2])
|
||
|
assert_nodes_equal(list(P), [0, 2])
|
||
|
assert_edges_equal(list(P.edges()), [(0, 2)])
|
||
|
P[0][2]['weight'] = 1
|
||
|
|
||
|
def test_star_projected_graph(self):
|
||
|
G = nx.star_graph(3)
|
||
|
P = bipartite.projected_graph(G, [1, 2, 3])
|
||
|
assert_nodes_equal(list(P), [1, 2, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 2), (1, 3), (2, 3)])
|
||
|
P = bipartite.weighted_projected_graph(G, [1, 2, 3])
|
||
|
assert_nodes_equal(list(P), [1, 2, 3])
|
||
|
assert_edges_equal(list(P.edges()), [(1, 2), (1, 3), (2, 3)])
|
||
|
|
||
|
P = bipartite.projected_graph(G, [0])
|
||
|
assert_nodes_equal(list(P), [0])
|
||
|
assert_edges_equal(list(P.edges()), [])
|
||
|
|
||
|
def test_project_multigraph(self):
|
||
|
G = nx.Graph()
|
||
|
G.add_edge('a', 1)
|
||
|
G.add_edge('b', 1)
|
||
|
G.add_edge('a', 2)
|
||
|
G.add_edge('b', 2)
|
||
|
P = bipartite.projected_graph(G, 'ab')
|
||
|
assert_edges_equal(list(P.edges()), [('a', 'b')])
|
||
|
P = bipartite.weighted_projected_graph(G, 'ab')
|
||
|
assert_edges_equal(list(P.edges()), [('a', 'b')])
|
||
|
P = bipartite.projected_graph(G, 'ab', multigraph=True)
|
||
|
assert_edges_equal(list(P.edges()), [('a', 'b'), ('a', 'b')])
|
||
|
|
||
|
def test_project_collaboration(self):
|
||
|
G = nx.Graph()
|
||
|
G.add_edge('a', 1)
|
||
|
G.add_edge('b', 1)
|
||
|
G.add_edge('b', 2)
|
||
|
G.add_edge('c', 2)
|
||
|
G.add_edge('c', 3)
|
||
|
G.add_edge('c', 4)
|
||
|
G.add_edge('b', 4)
|
||
|
P = bipartite.collaboration_weighted_projected_graph(G, 'abc')
|
||
|
assert P['a']['b']['weight'] == 1
|
||
|
assert P['b']['c']['weight'] == 2
|
||
|
|
||
|
def test_directed_projection(self):
|
||
|
G = nx.DiGraph()
|
||
|
G.add_edge('A', 1)
|
||
|
G.add_edge(1, 'B')
|
||
|
G.add_edge('A', 2)
|
||
|
G.add_edge('B', 2)
|
||
|
P = bipartite.projected_graph(G, 'AB')
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B')])
|
||
|
P = bipartite.weighted_projected_graph(G, 'AB')
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B')])
|
||
|
assert P['A']['B']['weight'] == 1
|
||
|
|
||
|
P = bipartite.projected_graph(G, 'AB', multigraph=True)
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B')])
|
||
|
|
||
|
G = nx.DiGraph()
|
||
|
G.add_edge('A', 1)
|
||
|
G.add_edge(1, 'B')
|
||
|
G.add_edge('A', 2)
|
||
|
G.add_edge(2, 'B')
|
||
|
P = bipartite.projected_graph(G, 'AB')
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B')])
|
||
|
P = bipartite.weighted_projected_graph(G, 'AB')
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B')])
|
||
|
assert P['A']['B']['weight'] == 2
|
||
|
|
||
|
P = bipartite.projected_graph(G, 'AB', multigraph=True)
|
||
|
assert_edges_equal(list(P.edges()), [('A', 'B'), ('A', 'B')])
|
||
|
|
||
|
|
||
|
class TestBipartiteWeightedProjection:
|
||
|
|
||
|
@classmethod
|
||
|
def setup_class(cls):
|
||
|
# Tore Opsahl's example
|
||
|
# http://toreopsahl.com/2009/05/01/projecting-two-mode-networks-onto-weighted-one-mode-networks/
|
||
|
cls.G = nx.Graph()
|
||
|
cls.G.add_edge('A', 1)
|
||
|
cls.G.add_edge('A', 2)
|
||
|
cls.G.add_edge('B', 1)
|
||
|
cls.G.add_edge('B', 2)
|
||
|
cls.G.add_edge('B', 3)
|
||
|
cls.G.add_edge('B', 4)
|
||
|
cls.G.add_edge('B', 5)
|
||
|
cls.G.add_edge('C', 1)
|
||
|
cls.G.add_edge('D', 3)
|
||
|
cls.G.add_edge('E', 4)
|
||
|
cls.G.add_edge('E', 5)
|
||
|
cls.G.add_edge('E', 6)
|
||
|
cls.G.add_edge('F', 6)
|
||
|
# Graph based on figure 6 from Newman (2001)
|
||
|
cls.N = nx.Graph()
|
||
|
cls.N.add_edge('A', 1)
|
||
|
cls.N.add_edge('A', 2)
|
||
|
cls.N.add_edge('A', 3)
|
||
|
cls.N.add_edge('B', 1)
|
||
|
cls.N.add_edge('B', 2)
|
||
|
cls.N.add_edge('B', 3)
|
||
|
cls.N.add_edge('C', 1)
|
||
|
cls.N.add_edge('D', 1)
|
||
|
cls.N.add_edge('E', 3)
|
||
|
|
||
|
def test_project_weighted_shared(self):
|
||
|
edges = [('A', 'B', 2),
|
||
|
('A', 'C', 1),
|
||
|
('B', 'C', 1),
|
||
|
('B', 'D', 1),
|
||
|
('B', 'E', 2),
|
||
|
('E', 'F', 1)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.weighted_projected_graph(self.G, 'ABCDEF')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
edges = [('A', 'B', 3),
|
||
|
('A', 'E', 1),
|
||
|
('A', 'C', 1),
|
||
|
('A', 'D', 1),
|
||
|
('B', 'E', 1),
|
||
|
('B', 'C', 1),
|
||
|
('B', 'D', 1),
|
||
|
('C', 'D', 1)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.weighted_projected_graph(self.N, 'ABCDE')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
def test_project_weighted_newman(self):
|
||
|
edges = [('A', 'B', 1.5),
|
||
|
('A', 'C', 0.5),
|
||
|
('B', 'C', 0.5),
|
||
|
('B', 'D', 1),
|
||
|
('B', 'E', 2),
|
||
|
('E', 'F', 1)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.collaboration_weighted_projected_graph(self.G, 'ABCDEF')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
edges = [('A', 'B', 11 / 6.0),
|
||
|
('A', 'E', 1 / 2.0),
|
||
|
('A', 'C', 1 / 3.0),
|
||
|
('A', 'D', 1 / 3.0),
|
||
|
('B', 'E', 1 / 2.0),
|
||
|
('B', 'C', 1 / 3.0),
|
||
|
('B', 'D', 1 / 3.0),
|
||
|
('C', 'D', 1 / 3.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.collaboration_weighted_projected_graph(self.N, 'ABCDE')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
def test_project_weighted_ratio(self):
|
||
|
edges = [('A', 'B', 2 / 6.0),
|
||
|
('A', 'C', 1 / 6.0),
|
||
|
('B', 'C', 1 / 6.0),
|
||
|
('B', 'D', 1 / 6.0),
|
||
|
('B', 'E', 2 / 6.0),
|
||
|
('E', 'F', 1 / 6.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.weighted_projected_graph(self.G, 'ABCDEF', ratio=True)
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
edges = [('A', 'B', 3 / 3.0),
|
||
|
('A', 'E', 1 / 3.0),
|
||
|
('A', 'C', 1 / 3.0),
|
||
|
('A', 'D', 1 / 3.0),
|
||
|
('B', 'E', 1 / 3.0),
|
||
|
('B', 'C', 1 / 3.0),
|
||
|
('B', 'D', 1 / 3.0),
|
||
|
('C', 'D', 1 / 3.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.weighted_projected_graph(self.N, 'ABCDE', ratio=True)
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
def test_project_weighted_overlap(self):
|
||
|
edges = [('A', 'B', 2 / 2.0),
|
||
|
('A', 'C', 1 / 1.0),
|
||
|
('B', 'C', 1 / 1.0),
|
||
|
('B', 'D', 1 / 1.0),
|
||
|
('B', 'E', 2 / 3.0),
|
||
|
('E', 'F', 1 / 1.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.overlap_weighted_projected_graph(self.G, 'ABCDEF', jaccard=False)
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
edges = [('A', 'B', 3 / 3.0),
|
||
|
('A', 'E', 1 / 1.0),
|
||
|
('A', 'C', 1 / 1.0),
|
||
|
('A', 'D', 1 / 1.0),
|
||
|
('B', 'E', 1 / 1.0),
|
||
|
('B', 'C', 1 / 1.0),
|
||
|
('B', 'D', 1 / 1.0),
|
||
|
('C', 'D', 1 / 1.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.overlap_weighted_projected_graph(self.N, 'ABCDE', jaccard=False)
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
def test_project_weighted_jaccard(self):
|
||
|
edges = [('A', 'B', 2 / 5.0),
|
||
|
('A', 'C', 1 / 2.0),
|
||
|
('B', 'C', 1 / 5.0),
|
||
|
('B', 'D', 1 / 5.0),
|
||
|
('B', 'E', 2 / 6.0),
|
||
|
('E', 'F', 1 / 3.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.overlap_weighted_projected_graph(self.G, 'ABCDEF')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in list(P.edges()):
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
edges = [('A', 'B', 3 / 3.0),
|
||
|
('A', 'E', 1 / 3.0),
|
||
|
('A', 'C', 1 / 3.0),
|
||
|
('A', 'D', 1 / 3.0),
|
||
|
('B', 'E', 1 / 3.0),
|
||
|
('B', 'C', 1 / 3.0),
|
||
|
('B', 'D', 1 / 3.0),
|
||
|
('C', 'D', 1 / 1.0)]
|
||
|
Panswer = nx.Graph()
|
||
|
Panswer.add_weighted_edges_from(edges)
|
||
|
P = bipartite.overlap_weighted_projected_graph(self.N, 'ABCDE')
|
||
|
assert_edges_equal(list(P.edges()), Panswer.edges())
|
||
|
for u, v in P.edges():
|
||
|
assert P[u][v]['weight'] == Panswer[u][v]['weight']
|
||
|
|
||
|
def test_generic_weighted_projected_graph_simple(self):
|
||
|
def shared(G, u, v):
|
||
|
return len(set(G[u]) & set(G[v]))
|
||
|
B = nx.path_graph(5)
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 2, 4], weight_function=shared)
|
||
|
assert_nodes_equal(list(G), [0, 2, 4])
|
||
|
assert_edges_equal(list(list(G.edges(data=True))),
|
||
|
[(0, 2, {'weight': 1}), (2, 4, {'weight': 1})])
|
||
|
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 2, 4])
|
||
|
assert_nodes_equal(list(G), [0, 2, 4])
|
||
|
assert_edges_equal(list(list(G.edges(data=True))),
|
||
|
[(0, 2, {'weight': 1}), (2, 4, {'weight': 1})])
|
||
|
B = nx.DiGraph()
|
||
|
nx.add_path(B, range(5))
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 2, 4])
|
||
|
assert_nodes_equal(list(G), [0, 2, 4])
|
||
|
assert_edges_equal(list(G.edges(data=True)),
|
||
|
[(0, 2, {'weight': 1}), (2, 4, {'weight': 1})])
|
||
|
|
||
|
def test_generic_weighted_projected_graph_custom(self):
|
||
|
def jaccard(G, u, v):
|
||
|
unbrs = set(G[u])
|
||
|
vnbrs = set(G[v])
|
||
|
return float(len(unbrs & vnbrs)) / len(unbrs | vnbrs)
|
||
|
|
||
|
def my_weight(G, u, v, weight='weight'):
|
||
|
w = 0
|
||
|
for nbr in set(G[u]) & set(G[v]):
|
||
|
w += G.edges[u, nbr].get(weight, 1) + G.edges[v, nbr].get(weight, 1)
|
||
|
return w
|
||
|
B = nx.bipartite.complete_bipartite_graph(2, 2)
|
||
|
for i, (u, v) in enumerate(B.edges()):
|
||
|
B.edges[u, v]['weight'] = i + 1
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 1],
|
||
|
weight_function=jaccard)
|
||
|
assert_edges_equal(list(G.edges(data=True)), [(0, 1, {'weight': 1.0})])
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 1],
|
||
|
weight_function=my_weight)
|
||
|
assert_edges_equal(list(G.edges(data=True)), [(0, 1, {'weight': 10})])
|
||
|
G = bipartite.generic_weighted_projected_graph(B, [0, 1])
|
||
|
assert_edges_equal(list(G.edges(data=True)), [(0, 1, {'weight': 2})])
|