def generate_graph(self): """ To be used after the data has been saved to an enrondump file by the parser :return: """ graph = Graph('Enron') emails = json.loads(open('enrondump').read()) for email in emails: sender_email = email['from'] if graph.has_node_by_label(sender_email): sender = graph.get_node_from_label(label=sender_email) else: sender = Node(label=sender_email) graph.add_node(sender) recipients = json.loads(email['To']) for recipient_email in recipients: if graph.has_node_by_label(recipient_email): recipient = graph.get_node_from_label(recipient_email) else: recipient = Node(label=recipient_email) graph.add_node(recipient) if not graph.has_edge(sender, recipient): graph.add_edge(sender, recipient, 1) else: # Increment the weight by 1 graph.update_edge(sender, recipient, graph.get_weight(sender, recipient,) + 1) return graph
def initialise_sample_graph(sample_graph): graph = Graph(name='SampleGraph') for each_node in sample_graph['nodes'].keys(): graph.add_node(Node(label=each_node)) for each_edge in sample_graph['weights'].keys(): node = graph.get_node_from_label(each_edge[0]) neighbor = graph.get_node_from_label(each_edge[1]) graph.add_edge(node, neighbor, sample_graph['weights'][each_edge]) return graph
class BasicGraphTest(unittest.TestCase): def setUp(self): """Call before every test case.""" self.graph_a = Graph(name="myGraph") # Simple graph with three nodes self.node1 = Node(label='node1') self.node2 = Node(label='node2') self.node3 = Node(label='node3') self.graph_a.add_node(self.node1) self.graph_a.add_node(self.node2, neighbors={self.node1}) self.graph_a.add_node(self.node3, neighbors={self.node1}) def tearDown(self): """Call after every test case.""" def test_init(self): """ Tests that everything done in the setUp method works correctly. This test includes - Confirming that the internal graph of form {<node1>:{<neighbor1>,<neighbor2>},...} is updated - Confirming that the internal weights of form {(<node1>,<node2>):weight),...} is updated - Confirming node.neighbors is updated. - Confirming that node.neighbors and node.weights always reflect each other. """ self.assertEqual(len(self.graph_a._graph), 3, "Node seems to be missing from _graph") self.assertEqual(len(self.graph_a._weights), 2, "Weight seems to be missing from _weights ") self.assertEqual( self.node2.get_neighbors(), {self.node1}, "Neighbor doesn't seem to be added at the node level") self.assertEqual( self.node3.get_neighbors(), {self.node1}, "Neighbor doesn't seem to be added at the node level") for node in self.graph_a._graph.keys(): neighbors = node.get_neighbors() if neighbors: for neighbor in neighbors: self.assertIn( (node, neighbor), self.graph_a._weights, "Weights don't seem to have updated correctly") def test_has_node(self): """ Test the has_node() method. The expectation is that passing any node that has been added to the graph returns True. :return: """ # hasNode successful cases self.assertTrue(self.graph_a.has_node(self.node1), "has_node() returning False when it should not") self.assertTrue(self.graph_a.has_node(self.node2), "has_node() returning False when it should not") self.assertTrue(self.graph_a.has_node(self.node3), "has_node() returning False when it should not") # hasNode failure cases fail_node1 = Node() # node that has been added as a neighbor outside of the graph fail_neighbor = Node() fail_node2 = Node(neighbors={fail_neighbor}) self.graph_a.add_node(fail_node2) # make sure node that has not been added returns false self.assertFalse( self.graph_a.has_node(fail_node1), "has_node() returns True for a node that has not been added") self.assertTrue(self.graph_a.has_node(fail_node2), "has_node() returning False when it should not") error_msg = "Returns True for node that has been added as a neighbor outside of the graph" self.assertFalse(self.graph_a.has_node(fail_neighbor), error_msg) def test_has_edge(self): """ Tests the has_edge method. The expectation is that passing any edge (directed) that has been added to the graph returns True. - Tests that the function returns True when expected - Tests that the function returns False when expected - Tests that the function raises an exception when either of the nodes are not in the graph :return: """ # hasEdge successful cases self.assertTrue(self.graph_a.has_edge(self.node2, self.node1), "has_edge() returning False when it should not") self.assertTrue(self.graph_a.has_edge(self.node3, self.node1), "has_edge() returning False when it should not") # hasEdge fail cases self.assertFalse(self.graph_a.has_edge(self.node1, self.node2), "has_edge() returning True when it should not") self.assertFalse(self.graph_a.has_edge(self.node1, self.node3), "has_edge() returning True when it should not") self.assertFalse(self.graph_a.has_edge(self.node3, self.node3), "has_edge() returning True for not-added self-edge") self.assertRaises(AssertionError, self.graph_a.has_edge, self.node1, Node()) self.assertRaises(AssertionError, self.graph_a.has_edge, Node(), self.node1) self.assertRaises(AssertionError, self.graph_a.has_edge, self.node2, Node({self.node2})) fail_node1 = Node() fail_neighbor = Node({fail_node1}) self.assertRaises(AssertionError, self.graph_a.has_edge, fail_node1, fail_neighbor) self.assertRaises(AssertionError, self.graph_a.has_edge, fail_neighbor, fail_node1) def test_add_node(self): """ Tests the add_node() method :return: """ # true cases self.assertIn(self.node1, self.graph_a._graph, "has_node failed to add nodes") self.assertIn(self.node2, self.graph_a._graph, "has_node failed to add nodes") self.assertIn(self.node3, self.graph_a._graph, "has_node failed to add nodes") # fail cases node4 = Node() node5 = Node() # incorrectly passed node #self.assertRaises(AssertionError,self.graph_a.add_node,(node4,node5)) self.assertRaises(AssertionError, self.graph_a.add_node, None) # incorrectly passed neighbors self.assertRaises(AssertionError, self.graph_a.add_node, node4, node5) self.assertRaises(AssertionError, self.graph_a.add_node, node5, node5) def test_add_edge(self): """ Tests adding edges between two existing nodes using the add_edge() method :return: """ # generic/correct use self.graph_a.add_edge(self.node2, self.node3) self.assertIn( (self.node2, self.node3), self.graph_a._weights) # tests that it was added to weights self.assertIn(self.node3, self.graph_a._graph[ self.node2]) # tests that it was added to _graph # adding multiple edges neighbor_list = [] for _ in range(400): temp_node = Node() neighbor_list.append(temp_node) self.graph_a.add_node(temp_node) self.graph_a.add_edge(self.node3, temp_node) for neighbor in neighbor_list: self.assertIn((self.node3, neighbor), self.graph_a._weights.keys() ) # tests that it was added to weights self.assertIn(neighbor, self.graph_a._graph[ self.node3]) # tests that it was added to _graph # add a -> b and b -> a for neighbor in neighbor_list: self.graph_a.add_edge(neighbor, self.node3) for neighbor in neighbor_list: self.assertIn((neighbor, self.node3), self.graph_a._weights.keys() ) # tests that it was added to weights self.assertIn(self.node3, self.graph_a._graph[neighbor] ) # tests that it was added to _graph def test_delete_node(self): """ test the delete_node method""" self.graph_a.add_edge(self.node1, self.node3) self.assertIn((self.node1, self.node3), self.graph_a._weights) self.assertIn((self.node3, self.node1), self.graph_a._weights) self.assertTrue(self.graph_a.has_node(self.node1)) self.graph_a.delete_node(self.node1) print(self.graph_a.get_all_edges(stringify=True)) self.assertFalse(self.graph_a.has_node(self.node1)) # confirm that the internal methods for clearing out the relationships were successful self.assertNotIn((self.node1, self.node3), self.graph_a._weights) self.assertNotIn((self.node3, self.node1), self.graph_a._weights) self.assertRaises(KeyError, self.graph_a._graph.__getitem__, self.node1) # confirm _graph neighbors have been deleted for node, neighbors in self.graph_a._graph.items(): print(self.node1, "|||", node) self.assertNotIn(self.node1, neighbors) self.assertNotIn(self.node1, self.graph_a._graph.keys()) def test_incoming_node_neighbors(self): self.assertEqual(self.graph_a.get_incoming_neighbors(self.node1), {self.node2, self.node3}) def test_thresholding(self): self.graph_a.add_edge(self.node1, self.node3, 4) self.graph_a.add_edge(self.node1, self.node2, 2) print(self.graph_a.get_threshold(25)) def test_save_graph(self): self.graph_a.load_save(self.graph_a.get_save())
class BasicGraphTest(unittest.TestCase): def setUp(self): """Call before every test case.""" self.basic_graph = Graph(name="myGraph") # Simple graph with three nodes self.node1 = Node(label='node1') self.node2 = Node(label='node2') self.node3 = Node(label='node3') self.basic_graph.add_node(self.node1) self.basic_graph.add_node(self.node2, neighbors={self.node1}) self.basic_graph.add_node(self.node3, neighbors={self.node1}) self.graph_algorithms = GraphAlgorithms() def tearDown(self): """Call after every test case.""" def test_node_count(self): node_count = self.graph_algorithms.node_count(self.basic_graph) self.assertEqual(node_count, 3) sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual(self.graph_algorithms.node_count(sample_graph_a), 5) def test_edge_count(self): edge_count = self.graph_algorithms.edge_count(self.basic_graph) self.assertEqual(edge_count, 2) sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual(self.graph_algorithms.edge_count(sample_graph_a), 5) def test_shortest_path(self): sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) paths = {} for source_node in sample_graph_a.get_all_nodes(): shortest_dist, prev = self.graph_algorithms.shortest_path_length( sample_graph_a, source_node) source_label = source_node.label length_list = [None] * 5 for node in shortest_dist.keys(): # print(source_label+'>'+node.label+':'+str(shortest_dist[node])) length_list.__setitem__(int(node.label), shortest_dist[node]) paths[source_label] = length_list # print(paths) # print(sample_graphs.graph_a['minpath']) self.assertEqual(paths, sample_graphs.graph_a['minpath']) def test_average_path(self): self.assertEqual( self.graph_algorithms.minimum_average_path(self.basic_graph), 1, "minimum average path failed") sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual( self.graph_algorithms.minimum_average_path(sample_graph_a), sample_graphs.graph_a['avgpath']) def test_diameter(self): self.assertEqual(self.graph_algorithms.diameter(self.basic_graph), 1, 'diameter algorithm failed for basic graph') sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual(self.graph_algorithms.diameter(sample_graph_a), sample_graphs.graph_a['diameter'], 'diameter algorithm failed for sample graph a') def test_mode_path(self): self.assertEqual( self.graph_algorithms.mode_path_length(self.basic_graph), (1, 2), 'mode_path_length algorithm failed for basic graph') sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual( self.graph_algorithms.mode_path_length(sample_graph_a), sample_graphs.graph_a['mode_path_length'], 'mode_path_length algorithm failed for sample graph a') def test_median_path(self): self.assertEqual( self.graph_algorithms.median_path_length(self.basic_graph), 1, 'median_path_length algorithm failed for basic graph') sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual( self.graph_algorithms.median_path_length(sample_graph_a), sample_graphs.graph_a['median_path_length'], 'median_path_length algorithm failed for sample graph a') def test_average_edges_per_node(self): self.assertEqual( self.graph_algorithms.average_edges_per_node(self.basic_graph), 0.67, 'average_edges_per_node algorithm failed for sample graph a') sample_graph_a = initialise_sample_graph(sample_graphs.graph_a) self.assertEqual( self.graph_algorithms.average_edges_per_node(sample_graph_a), 1.0, 'average_edges_per_node algorithm failed for sample graph a') def test_dfs(self): # todo finish test_dfs print( self.graph_algorithms.depth_first_search(self.basic_graph, self.node1)) def test_discover_components(self): # todo finish test_clustering sample_graph_b = initialise_sample_graph(sample_graphs.graph_b) print(self.graph_algorithms.discover_components(sample_graph_b)) def test_edmonds(self): sample_graph_c = initialise_sample_graph(sample_graphs.graph_c) source = sample_graph_c.get_node_from_label('0') sink = sample_graph_c.get_node_from_label('11') print(self.graph_algorithms.edmonds_karp(sample_graph_c, source, sink)) def test_local_clustering_coefficient(self): print( self.graph_algorithms.local_clustering_coefficient( self.basic_graph, self.node1)) def test_global_clustering_coefficient(self): print( self.graph_algorithms.average_clustering_coefficient( self.basic_graph)) def test_save_graph_agls(self): test_graph = Graph('test') test_graph.load_save(self.basic_graph.get_save()) print(self.graph_algorithms.node_count(test_graph)) def test_structural_holes(self): sample_graph_c = initialise_sample_graph(sample_graphs.graph_c) print(sample_graph_c.get_save()) print(self.graph_algorithms.structural_holes(sample_graph_c))