def test_VizTracingGraphviz_vertex_only(self): self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [5], 6: [6] } self.directed_graph = DirectedGraph(self.vertices) vertex_1 = self.directed_graph.get_vertex(1) vertex_1.set_attr("activated", True) vertex_2 = self.directed_graph.get_vertex(2) vertex_2.set_attr("in_cycle", True) dir = TestVizTracingGraphviz.RESOURCES_PATH_RECYCLE + "/" + \ inspect.currentframe().f_code.co_name pt.create_dir_in_user_home(dir) viz_cyclic_tracing: VizCyclicTracing = VizCyclicTracing( path=pt.get_dir_in_user_home(dir), directed_graph=self.directed_graph, vertex_states=[{ VizTracing.ACTIVATED: { "fillcolor": "red", "style": "filled" } }, { VizCyclicTracing.IN_CYCLE: { "fillcolor": "blue", "style": "filled" } }]) viz_cyclic_tracing.snapshot(self.directed_graph) self.assertTrue(True)
def test_indegree(self): vertex_to_test = 6 self.vertices = {0: [1], 1: [2, 3], 2: [3], 3: [4, vertex_to_test], 4: [5, vertex_to_test], 5: [5], vertex_to_test: []} self.directed_graph = DirectedGraph(self.vertices) vertex = self.directed_graph.get_vertex(vertex_to_test) self.assertEqual(vertex.get_indegree(), 2)
class TestDirectedGraphCyclic(unittest.TestCase): def setUp(self): pass def test_cyclic(self): Logging.enable() self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4], 4: [5, 2], 5: [6], 6: [7], 7: [5] } self.directed_graph = DirectedGraph(self.vertices) self.assertTrue(self.directed_graph.is_cyclic()) def test_acyclic(self): Logging.enable() self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [], 6: [] } self.directed_graph = DirectedGraph(self.vertices) self.assertFalse(self.directed_graph.is_cyclic()) def tearDown(self): pass
def test_get_reversed_small_graph_inplace_true(self): self.vertices = {0: [1], 1: [2], 2: []} self.directed_graph = DirectedGraph(self.vertices) reversed_graph = self.directed_graph.reversed(inplace=True) self.assertTrue(reversed_graph == self.directed_graph.get_direct_graph_core()) self.check_small_reversed_graph(reversed_graph)
class TestDirectedGraphTrail(unittest.TestCase): def setUp(self): pass def test_trail(self): self.vertices = { 0: [1, 2], 1: [3, 4], 2: [5, 6, 10], 3: [], 4: [], 5: [], 6: [7, 8], 8: [], 7: [9], 9: [2], 10: [11], 11: [] } self.directed_graph = DirectedGraph(self.vertices) self.directed_graph.trail(TestAdvisor()) for edge in self.directed_graph.get_edges(): self.assertEqual(edge.get_attr(COUNT), 1) def tearDown(self): pass
def test_VizTracingGraphviz_activate_vertex(self): self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [5], 6: [6] } self.directed_graph = DirectedGraph(self.vertices) vertex_1 = self.directed_graph.get_vertex(1) dir = TestVizTracingGraphviz.RESOURCES_PATH_RECYCLE + "/" + \ inspect.currentframe().f_code.co_name viz_cyclic_tracing: VizCyclicTracing = VizCyclicTracing( path=pt.get_dir_in_user_home(dir), directed_graph=self.directed_graph, vertex_states=[{ VizTracing.ACTIVATED: { "fillcolor": "red", "style": "filled" } }, { VizCyclicTracing.IN_CYCLE: { "fillcolor": "blue", "style": "filled" } }]) viz_cyclic_tracing.change_activated_vertex(self.directed_graph, vertex_1) for vertex in self.directed_graph.get_vertices(): if str(vertex_1.get_label()) == str(vertex.get_label()): self.assertTrue(vertex.get_attr(VizTracing.ACTIVATED)) else: self.assertFalse(vertex.get_attr(VizTracing.ACTIVATED))
def snapshot(self, directed_graph: DirectedGraph): """ Take a snapshot of the current directed graph Args: directed_graph (DirectedGraph): The directed graph """ dg = nx.DiGraph() vertex: Vertex for vertex in directed_graph.get_vertices(): dg.add_node(vertex.get_label()) edge: Edge for edge in directed_graph.get_edges(): dg.add_edge(edge.get_tail().get_label(), edge.get_head().get_label()) edges = [(u, v) for (u, v, _) in dg.edges(data=True)] pos = nx.planar_layout(dg) activated_nodes = self.get_nodes_by_state(directed_graph, VizTracing.ACTIVATED) visisted_nodes =\ self.get_nodes_by_state(directed_graph, VizTracing.VISITED) -\ activated_nodes default_nodes = {vertex.get_label() for vertex in directed_graph.get_vertices()} -\ visisted_nodes - activated_nodes self.draw_nodes(dg, pos, list(activated_nodes), directed_graph, VizTracing.ACTIVATED) self.draw_nodes(dg, pos, list(visisted_nodes), directed_graph, VizTracing.VISITED) self.draw_nodes(dg, pos, list(default_nodes), directed_graph, VizTracing.DEFAULT) nx.draw_networkx_edges(G=dg, pos=pos, edgelist=edges, width=VizTracingNetworkx.EDGE_WIDTH, edge_color=VizTracingNetworkx.EDGE_COLOR, style=VizTracingNetworkx.EDGE_STYLE, arrowsize=VizTracingNetworkx.EDGE_ARROW_SIZE) nx.draw_networkx_labels( G=dg, pos=pos, font_size=VizTracingNetworkx.NODE_FONT_SIZE, font_family=VizTracingNetworkx.NODE_FONT_FAMILY) plt.axis('off') plt.show() a = 100
class TestDirectedGraphSCCs(unittest.TestCase): def setUp(self): pass def test_create_sccs_nontrivial(self): self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4], 4: [5, 2], 5: [6], 6: [7], 7: [5], 8: [8] } self.directed_graph = DirectedGraph(self.vertices) sccs_labels = { frozenset(v.get_label() for v in s) for s in self.directed_graph.create_sccs_kosaraju_dfs() } sccs_expected = { frozenset([2, 3, 4]), frozenset([5, 6, 7]), frozenset([8]) } self.assertTrue(sccs_expected == sccs_labels) def test_create_sccs_trivial(self): self.vertices = { 0: [1], 1: [2, 3], 2: [0], 3: [4], 4: [5], 5: [3], 6: [5, 7], 7: [8], 8: [9], 9: [6, 10], 10: [] } self.directed_graph = DirectedGraph(self.vertices) sccs_labels = { frozenset(v.get_label() for v in s) for s in self.directed_graph.create_sccs_kosaraju_dfs( nontrivial=False) } sccs_expected = \ {frozenset([0, 1, 2]), frozenset([3, 4, 5]), frozenset([6, 7, 8, 9]), frozenset([10])} self.assertTrue(sccs_expected == sccs_labels) def tearDown(self): pass
def setUp(self): self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [5], 6: [6] } self.directed_graph = DirectedGraph(self.vertices)
def test_ordering(self): self.vertices = {5: [5], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 0: [1], 6: [6]} self.directed_graph = DirectedGraph(self.vertices, AlgorithmOrdering.ASC) self.assertTrue(next(iter( self.directed_graph.get_vertices())).get_label() == 0) self.directed_graph = DirectedGraph(self.vertices, AlgorithmOrdering.DESC) self.assertTrue(next(iter( self.directed_graph.get_vertices())).get_label() == 6)
def test_acyclic(self): Logging.enable() self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [], 6: [] } self.directed_graph = DirectedGraph(self.vertices) self.assertFalse(self.directed_graph.is_cyclic())
def test_cyclic(self): Logging.enable() self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4], 4: [5, 2], 5: [6], 6: [7], 7: [5] } self.directed_graph = DirectedGraph(self.vertices) self.assertTrue(self.directed_graph.is_cyclic())
def test_VizSccTracing_nontrivial(self): """ Functions more as a demonstration than as a test. It will create the animation for an acyclic graph""" self.directed_graph = \ DirectedGraph(self.vertices, algorithm_ordering=AlgorithmOrdering.ASC) dir = TestVizSccsKosarajuTracing.RESOURCES_PATH + "/" + \ inspect.currentframe().f_code.co_name viz_sccs_kosaraju_tracing: VizSccsKosarajuTracing =\ VizSccsKosarajuTracing( path=pt.get_dir_in_user_home(dir), directed_graph=self.directed_graph, vertex_states={ VizTracing.ACTIVATED: {"fillcolor": "red", "style": "filled"}, VizTracing.VISITED: {"fillcolor": "gray", "style": "filled"}, VizTracing.DEFAULT: {"fillcolor": "white", "style": "filled"} }, edge_states={}) viz_sccs_kosaraju_tracing.execute(resource_path=dir, nontrivial=True) self.assertTrue(True)
def test_VizCyclicTracing_cyclic(self): """ Functions more as a demonstration than as a test. It will create the animation for a cyclic graph""" self.vertices = {0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [7, 8], 6: [7, 8], 7: [9, 10, 11], 8: [3], 9: [], 10: [11], 11: [12], 12: []} self.directed_graph = \ DirectedGraph(self.vertices, algorithm_ordering=AlgorithmOrdering.ASC) dir = TestVizCyclicTracing.RESOURCES_PATH + "/" + \ inspect.currentframe().f_code.co_name viz_cyclic_tracing: VizCyclicTracing = VizCyclicTracing( path=pt.get_dir_in_user_home(dir), directed_graph=self.directed_graph, vertex_states=[ {VizTracing.ACTIVATED: {"fillcolor": "red", "style": "filled"}}, {VizCyclicTracing.IN_CYCLE: {"fillcolor": "blue", "style": "filled"}}, {VizCyclicTracing.VISITED: {"fillcolor": "gray", "style": "filled"}}]) viz_cyclic_tracing.execute(resource_path=dir) self.assertTrue(True)
def get_nodes_by_state(self, directed_graph: DirectedGraph, state: str) -> Set[str]: return { vertex.get_label() for vertex in directed_graph.get_vertices() if vertex.has_enabled_attr(state) }
def has_vertex_label_as_head2( self, graph: DirectedGraph, vertex_label: Union[str, int], head_label: Union[str, int]) -> bool: return True if head_label in \ {v.get_label() for v in graph.get_vertex(vertex_label).get_edge_heads()} \ else False
def deactivate_graph(self, directed_graph: DirectedGraph): """ Method that resets the whole graph Args: directed_graph (DirectedGraph): The directed graph """ for v in directed_graph.get_vertices(): self.reset_status(v, VizTracing.ACTIVATED)
def activate_graph(self, directed_graph: DirectedGraph): """ Method that sets the attribute "active" of all vertices to true. Args: directed_graph (DirectedGraph): The directed graph """ for v in directed_graph.get_vertices(): self.set_status(v, VizTracing.ACTIVATED)
def reset_attrs(self, directed_graph: DirectedGraph): """ Method that resets all attributes of a vertex Args: directed_graph (DirectedGraph): The directed graph vertex(Vertex): the vertex to be activated """ for v in directed_graph.get_vertices(): v.reset_attrs()
def snapshot(self, directed_graph: DirectedGraph): """ Take a snapshot of the current directed graph Args: directed_graph (DirectedGraph): The directed graph """ graph = Digraph(format=VizTracingGraphviz.IMAGE_TYPE) for vertex in directed_graph.get_vertices(): found = False default_state: Union[Mapping[str, str], None] = {} for state in self.vertex_states: attr_name, attr_values = next(iter(state.items())) if attr_name != VizTracing.DEFAULT and\ vertex.get_attr(attr_name): graph.node(name=str(vertex.get_label()), label=self.get_extended_label(vertex), _attributes=None, **attr_values) found = True break elif attr_name == VizTracing.DEFAULT: default_state = attr_values if not found: graph.node(name=str(vertex.get_label()), label=self.get_extended_label(vertex), _attributes=None, **default_state or {}) for edge in vertex.get_edges(): found = False default_state: Union[Mapping[str, str], None] = {} for state in self.edge_states: attr_name, attr_values = next(iter(state.items())) if attr_name != VizTracing.DEFAULT and \ edge.get_attr(attr_name): graph.edge(str(edge.get_tail().get_label()), str(edge.get_head().get_label()), label=None, _attributes=None, **attr_values) found = True break elif attr_name == VizTracing.DEFAULT: default_state = attr_values if not found: graph.edge(str(edge.get_tail().get_label()), str(edge.get_head().get_label())) graph.render( path.join( self.path, VizTracingGraphviz.IMAGE_NAME_PREFIX + ("{:04d}".format(self.snapshot_no)))) self.snapshot_no += 1
def change_activated_vertex(self, directed_graph: DirectedGraph, vertex: Vertex): """ Method that sets the attribute "active" of the vertex to true. It deactivates all other vertices Args: directed_graph (DirectedGraph): The directed graph vertex(Vertex): the vertex to be activated """ self.set_status(vertex, VizTracing.ACTIVATED) for v in directed_graph.get_vertices(): if str(v.get_label()) != str(vertex.get_label()): self.reset_status(v, VizTracing.ACTIVATED)
def test_create_sccs_nontrivial(self): self.vertices = { 0: [1], 1: [2, 3], 2: [3], 3: [4], 4: [5, 2], 5: [6], 6: [7], 7: [5], 8: [8] } self.directed_graph = DirectedGraph(self.vertices) sccs_labels = { frozenset(v.get_label() for v in s) for s in self.directed_graph.create_sccs_kosaraju_dfs() } sccs_expected = { frozenset([2, 3, 4]), frozenset([5, 6, 7]), frozenset([8]) } self.assertTrue(sccs_expected == sccs_labels)
class TestEdge(unittest.TestCase): def setUp(self): self.vertices = {0: [1], 1: [2], 2: [], 3: [6, 5, 4], 6: [], 5: [], 4: []} self.directed_graph = DirectedGraph(self.vertices) def test_reverse_edge(self): vertex1 = self.directed_graph.get_vertex(1) vertex2 = self.directed_graph.get_vertex(2) edge = next(iter(vertex1.get_edges())) edge.reverse() self.assertTrue(edge.get_tail() == vertex2) self.assertTrue(edge.get_head() == vertex1) def test_get_edges_ascending_order(self): self.directed_graph = DirectedGraph( self.vertices, algorithm_ordering=AlgorithmOrdering.ASC) self.assertTrue(next(iter( self.directed_graph.get_vertex(3).get_edges())) .get_head().get_label() == 4) def tearDown(self): pass
def test_create_sccs_trivial(self): self.vertices = { 0: [1], 1: [2, 3], 2: [0], 3: [4], 4: [5], 5: [3], 6: [5, 7], 7: [8], 8: [9], 9: [6, 10], 10: [] } self.directed_graph = DirectedGraph(self.vertices) sccs_labels = { frozenset(v.get_label() for v in s) for s in self.directed_graph.create_sccs_kosaraju_dfs( nontrivial=False) } sccs_expected = \ {frozenset([0, 1, 2]), frozenset([3, 4, 5]), frozenset([6, 7, 8, 9]), frozenset([10])} self.assertTrue(sccs_expected == sccs_labels)
def create_node_buckets(self, directed_graph: DirectedGraph) ->\ Dict[str, List[Vertex]]: """ Create different buckets that fit nodes with the same characteristics Args: directed_graph: The directed graph Returns: A dictionary that contains lists of vertices per characteristic """ mapping: Dict[str, List[Vertex]] = dict() for vertex in directed_graph.get_vertices(): if VizTracing.ACTIVATED in vertex.get_attrs(): mapping[VizTracing.ACTIVATED].append(vertex) elif VizTracing.VISITED in vertex.get_attrs(): mapping[VizTracing.VISITED].append(vertex) else: mapping[VizTracing.DEFAULT].append(vertex) return mapping
class TestDirectedGraph(unittest.TestCase): def setUp(self): self.vertices = {0: [1], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 5: [5], 6: [6]} self.directed_graph = DirectedGraph(self.vertices) def test_init(self): self.assertEqual(len(self.vertices.keys()), self.directed_graph.get_vertices_count()) def test_str(self): print(self.directed_graph) def test_one_vertex_self_loop(self): self.vertices = {0: [0]} self.directed_graph = DirectedGraph(self.vertices) def test_add_vertex(self): label = 7 self.directed_graph.add_vertex(label) vertex = self.directed_graph.get_vertex(label) self.assertIsNotNone(vertex) self.assertEqual(vertex.get_outdegree(), 0) self.assertEqual(vertex.get_indegree(), 0) self.assertListEqual(vertex.get_edge_heads(), list()) def test_add_duplicate_vertex(self): label = 7 self.directed_graph.add_vertex(label) with self.assertRaises(RuntimeError): self.directed_graph.add_vertex(label) def test_add_heads(self): vertex_to_test = 7 self.directed_graph.add_vertex(vertex_to_test) vertex = self.directed_graph.get_vertex(vertex_to_test) no_heads = 3 for i in range(no_heads): vertex.add_edge(self.directed_graph.get_vertex(i)) self.assertEqual(len(vertex.get_edge_heads()), no_heads) self.assertEqual(vertex.get_outdegree(), len(vertex.get_edge_heads())) def test_outdegree(self): vertex = self.directed_graph.get_vertex(1) self.assertEqual(vertex.get_outdegree(), len(vertex.get_edge_heads())) def test_indegree(self): vertex_to_test = 6 self.vertices = {0: [1], 1: [2, 3], 2: [3], 3: [4, vertex_to_test], 4: [5, vertex_to_test], 5: [5], vertex_to_test: []} self.directed_graph = DirectedGraph(self.vertices) vertex = self.directed_graph.get_vertex(vertex_to_test) self.assertEqual(vertex.get_indegree(), 2) def test_get_reversed_graph(self): self.directed_graph = DirectedGraph(self.vertices) self.directed_graph.reversed(inplace=True) self.check_big_reversed_graph(self.directed_graph) def test_get_reversed_small_graph_inplace_false(self): self.vertices = {0: [1], 1: [2], 2: []} self.directed_graph = DirectedGraph(self.vertices) reversed_graph = self.directed_graph.reversed(inplace=False) self.assertTrue(reversed_graph != self.directed_graph.get_direct_graph_core()) self.check_small_reversed_graph(reversed_graph) def test_get_reversed_small_graph_inplace_true(self): self.vertices = {0: [1], 1: [2], 2: []} self.directed_graph = DirectedGraph(self.vertices) reversed_graph = self.directed_graph.reversed(inplace=True) self.assertTrue(reversed_graph == self.directed_graph.get_direct_graph_core()) self.check_small_reversed_graph(reversed_graph) def test_ordering(self): self.vertices = {5: [5], 1: [2, 3], 2: [3], 3: [4, 6], 4: [5, 6], 0: [1], 6: [6]} self.directed_graph = DirectedGraph(self.vertices, AlgorithmOrdering.ASC) self.assertTrue(next(iter( self.directed_graph.get_vertices())).get_label() == 0) self.directed_graph = DirectedGraph(self.vertices, AlgorithmOrdering.DESC) self.assertTrue(next(iter( self.directed_graph.get_vertices())).get_label() == 6) def tearDown(self): pass def check_small_reversed_graph(self, reversed_graph): self.assertTrue(self.amount_of_tails2(reversed_graph, 2) == 1) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 2, 1)) self.assertTrue(self.amount_of_tails2(reversed_graph, 1) == 1) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 1, 0)) self.assertTrue(self.amount_of_tails2(reversed_graph, 0) == 0) def check_big_reversed_graph(self, reversed_graph): self.assertTrue(self.amount_of_tails2(reversed_graph, 6) == 3) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 6, 4)) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 6, 6)) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 6, 3)) self.assertTrue(self.amount_of_tails2(reversed_graph, 5) == 2) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 5, 5)) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 5, 4)) self.assertTrue(self.amount_of_tails2(reversed_graph, 4) == 1) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 4, 3)) self.assertTrue(self.amount_of_tails2(reversed_graph, 3) == 2) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 3, 1)) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 3, 2)) self.assertTrue(self.amount_of_tails2(reversed_graph, 2) == 1) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 2, 1)) self.assertTrue(self.amount_of_tails2(reversed_graph, 1) == 1) self.assertTrue(self.has_vertex_label_as_head2(reversed_graph, 1, 0)) self.assertTrue(self.amount_of_tails2(reversed_graph, 0) == 0) def has_vertex_label_as_head( self, graph: DirectedGraphCore, vertex_label: Union[str, int], head_label: Union[str, int]) -> bool: return True if head_label in \ {v.get_label() for v in graph.get_vertex(vertex_label).get_edge_heads()} \ else False def amount_of_heads( self, graph: DirectedGraphCore, vertex_label: Union[str, int]) -> int: return len(graph.get_vertex(vertex_label).get_edge_heads()) def has_vertex_label_as_head2( self, graph: DirectedGraph, vertex_label: Union[str, int], head_label: Union[str, int]) -> bool: return True if head_label in \ {v.get_label() for v in graph.get_vertex(vertex_label).get_edge_heads()} \ else False def amount_of_tails2( self, graph: DirectedGraph, vertex_label: Union[str, int]) -> int: return len(graph.get_vertex(vertex_label).get_edge_heads())
def test_get_edges_ascending_order(self): self.directed_graph = DirectedGraph( self.vertices, algorithm_ordering=AlgorithmOrdering.ASC) self.assertTrue(next(iter( self.directed_graph.get_vertex(3).get_edges())) .get_head().get_label() == 4)
def test_get_reversed_graph(self): self.directed_graph = DirectedGraph(self.vertices) self.directed_graph.reversed(inplace=True) self.check_big_reversed_graph(self.directed_graph)
def test_one_vertex_self_loop(self): self.vertices = {0: [0]} self.directed_graph = DirectedGraph(self.vertices)
def amount_of_tails2( self, graph: DirectedGraph, vertex_label: Union[str, int]) -> int: return len(graph.get_vertex(vertex_label).get_edge_heads())