def build_digraph(degree_sequence, nodes=None): ''' Generates directed graph of the given degree sequence (out, in). If nodes are provided, each node will have the corresponding data. ''' if not is_valid_directed_degree_sequence(degree_sequence): raise InvalidDegreeSequence('Invalid degree sequence!') graph = DiGraph() degree_node = [] if not nodes: nodes = count() for item in map(lambda x, z: [x[0], x[1], z], degree_sequence, nodes): degree_node.append(item) degree_node.sort(key=lambda x: x[1], reverse=True) degree_node.sort(key=lambda x: x[0], reverse=True) degree_node = deque(degree_node) while degree_node: out_degree, in_degree, node = degree_node.popleft() if in_degree == out_degree == 0: graph.add_node(node) continue for out_in_node in degree_node: if out_degree == 0: break if out_in_node[1]: out_in_node[1] -= 1 out_degree -= 1 graph.add_edge(node, out_in_node[2]) if in_degree: degree_node.append([out_degree, in_degree, node]) return graph
class BasicDiGraphTest(unittest.TestCase): def setUp(self): self.nodes = [1, 'Sofia', 'Bourgas', 5.6555] self.edges = [(1, 'Sofia'), ('Sofia', 'Bourgas')] self.graph = DiGraph() for node in self.nodes: self.graph.add_node(node) for edge in self.edges: self.graph.add_edge(*edge) def tearDown(self): del self.nodes del self.graph def test_nodes_in_graph(self): for node in self.nodes: self.assertTrue(node in self.graph) self.assertFalse('NotANode' in self.graph) def test_edges_successors_predecessors(self): for (u, v) in self.edges: self.assertTrue(u in self.graph.get_predecessors(v)) self.assertTrue(v in self.graph.get_successors(u)) self.assertFalse(v in self.graph.get_predecessors(u)) self.assertFalse(u in self.graph.get_successors(v)) def test_has_edge(self): for (u, v) in self.edges: self.assertTrue(self.graph.has_edge(u, v)) def test_remove_edge(self): u, v = 1, 'Bourgas' self.assertFalse(self.graph.has_edge(u, v)) self.graph.add_edge(u, v) self.assertTrue(self.graph.has_edge(u, v)) self.graph.remove_edge(u, v) self.assertFalse(self.graph.has_edge(u, v)) def test_is_directed(self): self.assertTrue(self.graph.is_directed()) def test_in_degree(self): self.assertEqual(self.graph.in_degree('Sofia'), 1) self.assertEqual(self.graph.in_degree(1), 0) def test_out_degree(self): self.assertEqual(self.graph.out_degree('Sofia'), 1) self.assertEqual(self.graph.out_degree('Bourgas'), 0) def test_degree(self): self.assertEqual(self.graph.degree('Sofia'), 2) self.assertEqual(self.graph.degree(5.6555), 0) def test_order(self): self.assertEqual(self.graph.order(), len(self.nodes)) self.graph.add_node('AloneNode') self.assertEqual(self.graph.order(), len(self.nodes)+1) self.graph.remove_node('AloneNode') self.assertEqual(self.graph.order(), len(self.nodes)) def test_size(self): self.assertEqual(self.graph.size(), len(self.edges)) self.graph.add_edge(100, 100) self.assertEqual(self.graph.size(), len(self.edges) + 1) self.graph.remove_node(100) self.assertEqual(self.graph.size(), len(self.edges))