Beispiel #1
0
    def test_vertex_add_parent(self):
        vertex = Vertex()
        parent_vertex = Vertex()
        vertex.add_parent(parent_vertex)

        self.assertEqual(vertex.parents, [parent_vertex])
        self.assertEqual(parent_vertex.children, [vertex])
Beispiel #2
0
    def test_vertex_add_child(self):
        vertex = Vertex()
        child_vertex = Vertex()
        vertex.add_child(child_vertex)

        self.assertEqual(vertex.children, [child_vertex])
        self.assertEqual(child_vertex.parents, [vertex])
Beispiel #3
0
    def setUp(self):
        # Create a DAG
        #          +--> vertex_1 --> vertex_4 -->+
        # vertex_0 |--> vertex_2                 |--> vertex_5
        #          +--> vertex_3 --------------->+
        self.vertex_0 = Vertex()
        self.vertex_1 = Vertex()
        self.vertex_2 = Vertex()
        self.vertex_3 = Vertex()
        self.vertex_4 = Vertex()
        self.vertex_5 = Vertex()

        self.vertex_0.add_child(self.vertex_1)
        self.vertex_0.add_child(self.vertex_2)
        self.vertex_0.add_child(self.vertex_3)
        self.vertex_1.add_child(self.vertex_4)
        self.vertex_3.add_child(self.vertex_5)
        self.vertex_4.add_child(self.vertex_5)
Beispiel #4
0
    def test_traverse_with_simple_graph(self):
        vertex_0 = Vertex()
        vertex_1 = Vertex()
        vertex_2 = Vertex()

        # Create a simple DAG
        # vertex_0 -> vertex_1 -> vertex_2
        vertex_0.add_child(vertex_1)
        vertex_1.add_child(vertex_2)

        vertices = Stack()
        vertices.push(vertex_0)
        traversal_list = [v for v in traverse(vertices)]
        self.assertEqual(traversal_list, [vertex_0, vertex_1, vertex_2])

        # In this simple DAG, Stack or Queue shouldn't make any difference.
        vertices = Queue()
        vertices.push(vertex_0)
        traversal_list = [v for v in traverse(vertices)]
        self.assertEqual(traversal_list, [vertex_0, vertex_1, vertex_2])
Beispiel #5
0
class TestTopologicalWhile(unittest.TestCase):
    def setUp(self):
        # Create a DAG
        #          +--> vertex_1 --> vertex_4 -->+
        # vertex_0 |--> vertex_2                 |--> vertex_5
        #          +--> vertex_3 --------------->+
        self.vertex_0 = Vertex()
        self.vertex_1 = Vertex()
        self.vertex_2 = Vertex()
        self.vertex_3 = Vertex()
        self.vertex_4 = Vertex()
        self.vertex_5 = Vertex()

        self.vertex_0.add_child(self.vertex_1)
        self.vertex_0.add_child(self.vertex_2)
        self.vertex_0.add_child(self.vertex_3)
        self.vertex_1.add_child(self.vertex_4)
        self.vertex_3.add_child(self.vertex_5)
        self.vertex_4.add_child(self.vertex_5)

    def test_topological_while_iteration_never_done(self):
        # Don't mark any vertex as done.
        def done_check(vertex):
            return False

        # Don't ignore any vertex
        def ignore_check(vertex):
            return False

        total_count = 0
        vertex_counts = {
            self.vertex_0: 0,
            self.vertex_1: 0,
            self.vertex_2: 0,
            self.vertex_3: 0,
            self.vertex_4: 0,
            self.vertex_5: 0,
        }
        for vertex in topological_while(self.vertex_0, done_check,
                                        ignore_check):
            vertex_counts[vertex] += 1
            if total_count < 90:
                total_count += 1
            else:
                break

        # Topological while should not visit any other vertex because done_check always returns false.
        self.assertEqual(vertex_counts[self.vertex_0], 91)
        self.assertEqual(vertex_counts[self.vertex_1], 0)
        self.assertEqual(vertex_counts[self.vertex_2], 0)
        self.assertEqual(vertex_counts[self.vertex_3], 0)
        self.assertEqual(vertex_counts[self.vertex_4], 0)
        self.assertEqual(vertex_counts[self.vertex_5], 0)

    def test_topological_while_iteration_with_done(self):
        # Mark every returned vertex as done.
        def done_check(vertex):
            return True

        # Don't ignore any vertex
        def ignore_check(vertex):
            return False

        total_count = 0
        vertex_counts = {
            self.vertex_0: 0,
            self.vertex_1: 0,
            self.vertex_2: 0,
            self.vertex_3: 0,
            self.vertex_4: 0,
            self.vertex_5: 0,
        }
        for vertex in topological_while(self.vertex_0, done_check,
                                        ignore_check):
            vertex_counts[vertex] += 1
            if total_count < 90:
                total_count += 1
            else:
                break

        # Topological while should visit every vertex exactly equal to the number of its parents.
        self.assertEqual(vertex_counts[self.vertex_0], 1)
        self.assertEqual(vertex_counts[self.vertex_1], 1)
        self.assertEqual(vertex_counts[self.vertex_2], 1)
        self.assertEqual(vertex_counts[self.vertex_3], 1)
        self.assertEqual(vertex_counts[self.vertex_4], 1)
        self.assertEqual(vertex_counts[self.vertex_5], 2)

    def test_topological_while_iteration_with_ignore(self):
        # Don't mark any vertex as done.
        def done_check(vertex):
            return False

        # Ignore every vertex
        def ignore_check(vertex):
            return True

        total_count = 0
        vertex_counts = {
            self.vertex_0: 0,
            self.vertex_1: 0,
            self.vertex_2: 0,
            self.vertex_3: 0,
            self.vertex_4: 0,
            self.vertex_5: 0,
        }
        for vertex in topological_while(self.vertex_0, done_check,
                                        ignore_check):
            vertex_counts[vertex] += 1
            if total_count < 90:
                total_count += 1
            else:
                break

        # Topological while should not visit any vertex other than the root vertex.
        self.assertEqual(vertex_counts[self.vertex_0], 1)
        self.assertEqual(vertex_counts[self.vertex_1], 0)
        self.assertEqual(vertex_counts[self.vertex_2], 0)
        self.assertEqual(vertex_counts[self.vertex_3], 0)
        self.assertEqual(vertex_counts[self.vertex_4], 0)
        self.assertEqual(vertex_counts[self.vertex_5], 0)

    def test_topological_while_with_done_and_ignore_markers(self):
        visited_vertices = []
        ignored_vertices = []

        # Mark a vertex done if it has been marked as visited with the visted_marker
        def done_check(vertex):
            if vertex in visited_vertices:
                return True
            else:
                return False

        # Ignore vertices that have been marked with the ignore_marker
        def ignore_check(vertex):
            if vertex in ignored_vertices:
                return True
            else:
                return False

        total_count = 0
        vertex_counts = {
            self.vertex_0: 0,
            self.vertex_1: 0,
            self.vertex_2: 0,
            self.vertex_3: 0,
            self.vertex_4: 0,
            self.vertex_5: 0,
        }

        # For the DAG:
        #          +--> vertex_1 --> vertex_4 -->+
        # vertex_0 |--> vertex_2                 |--> vertex_5
        #          +--> vertex_3 --------------->+
        #
        # Mark vertex_1 as ignored and check that vertex_4 and vertex_5 are not visited.
        for vertex in topological_while(self.vertex_0, done_check,
                                        ignore_check):
            vertex_counts[vertex] += 1
            if vertex == self.vertex_1:
                ignored_vertices.append(vertex)  # mark this to ignore
            else:
                visited_vertices.append(vertex)  # mark this as done.

        # Topological while should not visit vertex_4 and vertex_5 and only once every other vertex
        self.assertEqual(vertex_counts[self.vertex_0], 1)
        self.assertEqual(vertex_counts[self.vertex_1], 1)
        self.assertEqual(vertex_counts[self.vertex_2], 1)
        self.assertEqual(vertex_counts[self.vertex_3], 1)
        self.assertEqual(vertex_counts[self.vertex_4], 0)
        self.assertEqual(vertex_counts[self.vertex_5], 0)

    def test_topological_traverse(self):
        # For the DAG:
        #          +--> vertex_1 --> vertex_4 -->+
        # vertex_0 |--> vertex_2                 |--> vertex_5
        #          +--> vertex_3 --------------->+
        #
        vertices = [v for v in topological_traverse(self.vertex_0)]

        vertex_0_pos = vertices.index(self.vertex_0)
        vertex_1_pos = vertices.index(self.vertex_1)
        vertex_2_pos = vertices.index(self.vertex_2)
        vertex_3_pos = vertices.index(self.vertex_3)
        vertex_4_pos = vertices.index(self.vertex_4)
        vertex_5_pos = vertices.index(self.vertex_5)

        # Check if the correct order is preserved
        self.assertLess(vertex_0_pos, vertex_1_pos)
        self.assertLess(vertex_0_pos, vertex_2_pos)
        self.assertLess(vertex_0_pos, vertex_3_pos)
        self.assertLess(vertex_1_pos, vertex_4_pos)
        self.assertLess(vertex_4_pos, vertex_5_pos)
        self.assertLess(vertex_3_pos, vertex_5_pos)
Beispiel #6
0
    def test_is_dag_acyclic(self):
        # Create an acyclic DAG
        # vertex_0 --> vertex_1 --> vertex_2
        vertex_0 = Vertex()
        vertex_1 = Vertex()
        vertex_2 = Vertex()
        vertex_0.add_child(vertex_1)
        vertex_1.add_child(vertex_2)

        # Create a cyclic DAG
        #    +------------+
        #    |            |
        #    v     +--> vertex_b
        # vertex_a |
        #          +--> vertex_c --> vertex_d
        vertex_a = Vertex()
        vertex_b = Vertex()
        vertex_c = Vertex()
        vertex_d = Vertex()
        vertex_a.add_child(vertex_b)
        vertex_b.add_child(vertex_a)
        vertex_a.add_child(vertex_c)
        vertex_c.add_child(vertex_d)

        self.assertTrue(is_dag_acyclic(vertex_0))
        self.assertFalse(is_dag_acyclic(vertex_a))
Beispiel #7
0
    def test_traverse_with_not_so_simple_graph(self):
        vertex_0 = Vertex()
        vertex_1 = Vertex()
        vertex_2 = Vertex()
        vertex_3 = Vertex()

        # Create a simple DAG
        # vertex_0 -> vertex_1 -> vertex_2
        #
        #             +--> vertex_1 -->+
        # vertex_0 -->|                |--> vertex_3
        #             +--> vertex_2 -->+
        vertex_0.add_child(vertex_1)
        vertex_0.add_child(vertex_2)
        vertex_1.add_child(vertex_3)
        vertex_2.add_child(vertex_3)

        vertex_counts = {
            vertex_0: 0,
            vertex_1: 0,
            vertex_2: 0,
            vertex_3: 0,
        }
        vertices = Stack()
        vertices.push(vertex_0)
        for vertex in traverse(vertices):
            vertex_counts[vertex] += 1

        # None of the vertices should have a count more than one.
        for vertex in vertex_counts:
            self.assertEqual(vertex_counts[vertex], 1)
Beispiel #8
0
 def test_vertex_instance(self):
     vertex = Vertex()
     self.assertIsInstance(vertex, Vertex)
     self.assertEqual(vertex.parents, [])
     self.assertEqual(vertex.children, [])
Beispiel #9
0
    def setUp(self):
        self.vertex_0 = Vertex()
        self.vertex_1 = Vertex()
        self.vertex_2 = Vertex()
        self.vertex_3 = Vertex()
        self.vertex_4 = Vertex()
        self.vertex_5 = Vertex()
        self.vertex_6 = Vertex()

        # Create a DAG
        #          +--> vertex_1 --> vertex_4
        # vertex_0 |--> vertex_2 --> vertex_5
        #          +--> vertex_3 --> vertex_6
        self.vertex_0.add_child(self.vertex_1)
        self.vertex_0.add_child(self.vertex_2)
        self.vertex_0.add_child(self.vertex_3)
        self.vertex_1.add_child(self.vertex_4)
        self.vertex_2.add_child(self.vertex_5)
        self.vertex_3.add_child(self.vertex_6)
Beispiel #10
0
class TestTraversalAlgorithms(unittest.TestCase):
    def setUp(self):
        self.vertex_0 = Vertex()
        self.vertex_1 = Vertex()
        self.vertex_2 = Vertex()
        self.vertex_3 = Vertex()
        self.vertex_4 = Vertex()
        self.vertex_5 = Vertex()
        self.vertex_6 = Vertex()

        # Create a DAG
        #          +--> vertex_1 --> vertex_4
        # vertex_0 |--> vertex_2 --> vertex_5
        #          +--> vertex_3 --> vertex_6
        self.vertex_0.add_child(self.vertex_1)
        self.vertex_0.add_child(self.vertex_2)
        self.vertex_0.add_child(self.vertex_3)
        self.vertex_1.add_child(self.vertex_4)
        self.vertex_2.add_child(self.vertex_5)
        self.vertex_3.add_child(self.vertex_6)

    def test_traverse_with_simple_graph(self):
        vertex_0 = Vertex()
        vertex_1 = Vertex()
        vertex_2 = Vertex()

        # Create a simple DAG
        # vertex_0 -> vertex_1 -> vertex_2
        vertex_0.add_child(vertex_1)
        vertex_1.add_child(vertex_2)

        vertices = Stack()
        vertices.push(vertex_0)
        traversal_list = [v for v in traverse(vertices)]
        self.assertEqual(traversal_list, [vertex_0, vertex_1, vertex_2])

        # In this simple DAG, Stack or Queue shouldn't make any difference.
        vertices = Queue()
        vertices.push(vertex_0)
        traversal_list = [v for v in traverse(vertices)]
        self.assertEqual(traversal_list, [vertex_0, vertex_1, vertex_2])

    def test_traverse_with_not_so_simple_graph(self):
        vertex_0 = Vertex()
        vertex_1 = Vertex()
        vertex_2 = Vertex()
        vertex_3 = Vertex()

        # Create a simple DAG
        # vertex_0 -> vertex_1 -> vertex_2
        #
        #             +--> vertex_1 -->+
        # vertex_0 -->|                |--> vertex_3
        #             +--> vertex_2 -->+
        vertex_0.add_child(vertex_1)
        vertex_0.add_child(vertex_2)
        vertex_1.add_child(vertex_3)
        vertex_2.add_child(vertex_3)

        vertex_counts = {
            vertex_0: 0,
            vertex_1: 0,
            vertex_2: 0,
            vertex_3: 0,
        }
        vertices = Stack()
        vertices.push(vertex_0)
        for vertex in traverse(vertices):
            vertex_counts[vertex] += 1

        # None of the vertices should have a count more than one.
        for vertex in vertex_counts:
            self.assertEqual(vertex_counts[vertex], 1)

    def test_breadth_first_traverse(self):
        traversal_list = [v for v in breadth_first_traverse(self.vertex_0)]

        # The traversal happened correctly if the index numbers of the
        # different vertex objects preserve the same order.
        #          +--> vertex_1 --> vertex_4
        # vertex_0 |--> vertex_2 --> vertex_5
        #          +--> vertex_3 --> vertex_6
        vertex_0_pos = traversal_list.index(self.vertex_0)
        vertex_1_pos = traversal_list.index(self.vertex_1)
        vertex_2_pos = traversal_list.index(self.vertex_2)
        vertex_3_pos = traversal_list.index(self.vertex_3)
        vertex_4_pos = traversal_list.index(self.vertex_4)
        vertex_5_pos = traversal_list.index(self.vertex_5)
        vertex_6_pos = traversal_list.index(self.vertex_6)
        # Assert local ordering ie., child vertices follow parents
        self.assertLess(vertex_0_pos, vertex_1_pos)
        self.assertLess(vertex_0_pos, vertex_2_pos)
        self.assertLess(vertex_0_pos, vertex_3_pos)
        self.assertLess(vertex_1_pos, vertex_4_pos)
        self.assertLess(vertex_2_pos, vertex_5_pos)
        self.assertLess(vertex_3_pos, vertex_6_pos)

        # Assert global ordering, no child vertices occur before any
        # parents due to breadth first traversal
        self.assertLess(vertex_1_pos, vertex_5_pos)
        self.assertLess(vertex_1_pos, vertex_6_pos)
        self.assertLess(vertex_2_pos, vertex_4_pos)
        self.assertLess(vertex_2_pos, vertex_6_pos)
        self.assertLess(vertex_3_pos, vertex_4_pos)
        self.assertLess(vertex_3_pos, vertex_5_pos)

    def test_depth_first_traverse(self):
        traversal_list = [v for v in depth_first_traverse(self.vertex_0)]

        # The traversal happened correctly if the index numbers of the
        # different vertex objects preserve the same order.
        #          +--> vertex_1 --> vertex_4
        # vertex_0 |--> vertex_2 --> vertex_5
        #          +--> vertex_3 --> vertex_6
        vertex_0_pos = traversal_list.index(self.vertex_0)
        vertex_1_pos = traversal_list.index(self.vertex_1)
        vertex_2_pos = traversal_list.index(self.vertex_2)
        vertex_3_pos = traversal_list.index(self.vertex_3)
        vertex_4_pos = traversal_list.index(self.vertex_4)
        vertex_5_pos = traversal_list.index(self.vertex_5)
        vertex_6_pos = traversal_list.index(self.vertex_6)
        # Assert local ordering ie., child vertices follow parents
        self.assertLess(vertex_0_pos, vertex_1_pos)
        self.assertLess(vertex_0_pos, vertex_2_pos)
        self.assertLess(vertex_0_pos, vertex_3_pos)
        self.assertLess(vertex_1_pos, vertex_4_pos)
        self.assertLess(vertex_2_pos, vertex_5_pos)
        self.assertLess(vertex_3_pos, vertex_6_pos)

        # Assert global ordering ie., there is atleast 1 vertex between
        # any of the vertices 1, 2 and 3 (due to depth first traversal).
        self.assertTrue(abs(vertex_1_pos - vertex_2_pos) > 1)
        self.assertTrue(abs(vertex_1_pos - vertex_3_pos) > 1)
        self.assertTrue(abs(vertex_2_pos - vertex_3_pos) > 1)