Example #1
0
    def test_status(self):
        # For different graphs
        # G0: 0 -- 1 -- 2 -- 3
        #                \  /
        #                 4 -- 5 -- 6
        #
        # G1: 10 -- 12 -- 13
        #            \   /
        #             14 -- 11 -- 15 -- 16
        #
        # G2: 21 -- 23 -- 25 -- 20 -- 26 -- 22
        #                   \  /
        #                    24
        #
        # G3: 30 -- 32 -- 34 -- 35 -- 36
        #                         \  /
        #                          31 -- 33
        G0 = create_graph_helper(edges=[[0, 1], [1, 2], [2, 3], [3, 4], [2, 4], [4, 5], [5, 6]])
        G1 = create_graph_helper(edges=[[10, 12], [12, 13], [12, 14], [13, 14], [11, 14], [11, 15], [15, 16]])
        G2 = create_graph_helper(edges=[[21, 23], [23, 25], [20, 25], [20, 24], [24, 25], [20, 26], [22, 26]])
        G3 = create_graph_helper(edges=[[30, 32], [32, 34], [34, 35], [35, 36], [31, 35], [31, 36], [31, 33]])

        coloring13 = create_coloring_helper(G1.vertices + G3.vertices,
                                            {0: [10, 33], 1: [16, 30], 2: [11, 34], 3: [13, 36], 4: [15, 32],
                                             5: [12, 31], 6: [14, 35]})
        coloring02 = create_coloring_helper(G0.vertices + G2.vertices,
                                            {0: [0, 6, 21, 22], 1: [1, 5, 23, 26], 2: [3, 24], 3: [2, 4, 20, 25]})
        coloring01 = create_coloring_helper(G0.vertices + G1.vertices,
                                            {0: [0, 6], 1: [1, 5], 2: [2, 4], 3: [3], 4: [10], 5: [11], 6: [12],
                                             7: [13], 8: [14], 9: [15], 10: [16]})
        unbalanced_coloring = create_coloring_helper(G0.vertices + G1.vertices, {0: [0, 1], 1: [10, 11]})

        self.assertEqual("Bijection", coloring13.status(G1, G3))
        self.assertEqual(None, coloring02.status(G1, G3))
        self.assertEqual("Unbalanced", coloring01.status(G1, G3))
        self.assertEqual("Unbalanced", unbalanced_coloring.status(G0, G1))

        # Automorphism
        G0copy = G0.deepcopy()
        coloring0 = create_coloring_helper(G0.vertices, {0: [0, 6], 1: [1, 5], 2: [2, 4], 3: [3]})
        coloring0.add([G0copy.vertices[0], G0copy.vertices[6]], 0)
        coloring0.add([G0copy.vertices[1], G0copy.vertices[5]], 1)
        coloring0.add([G0copy.vertices[2], G0copy.vertices[4]], 2)
        coloring0.set(G0copy.vertices[3], 3)
        self.assertEqual(None, coloring0.status(G0, G0copy))
    def test_initialize_and_unit_coloring(self):
        # empty graph
        g = Graph(False)
        init_coloring = initialize_coloring(g)
        self.assertEqual(0, len(init_coloring))

        # 1 - 2 - 3
        g = tools.create_graph_helper([(1, 2), (2, 3)])
        v_g1, v_g2, v_g3 = g.vertices
        init_coloring = initialize_coloring(g)
        self.assertEqual(2, len(init_coloring))
        self.assertListEqual([v_g1, v_g3], list(init_coloring.get(1)))
        self.assertListEqual([v_g2], list(init_coloring.get(2)))

        # 1 - 2 - 3
        #     |
        #     4 - 6 - 7
        #     |
        #     5
        g = tools.create_graph_helper([(1, 2), (2, 3), (2, 4), (4, 5), (4, 6),
                                       (6, 7)])
        v_g1, v_g2, v_g3, v_g4, v_g5, v_g6, v_g7 = g.vertices
        init_coloring = initialize_coloring(g)
        self.assertEqual(3, len(init_coloring))
        self.assertListEqual([v_g1, v_g3, v_g5, v_g7],
                             list(init_coloring.get(1)))
        self.assertListEqual([v_g6], list(init_coloring.get(2)))
        self.assertListEqual([v_g2, v_g4], list(init_coloring.get(3)))

        # 1 - 2 - 3
        #     |
        #     4 - 6 - 7
        #     |
        #     5       8
        v_g8 = Vertex(g)
        g.add_vertex(v_g8)
        init_coloring = initialize_coloring(g)
        self.assertEqual(4, len(init_coloring))
        self.assertListEqual([v_g8], list(init_coloring.get(0)))
        self.assertListEqual([v_g1, v_g3, v_g5, v_g7],
                             list(init_coloring.get(1)))
        self.assertListEqual([v_g6], list(init_coloring.get(2)))
        self.assertListEqual([v_g2, v_g4], list(init_coloring.get(3)))
Example #3
0
    def test_moeilijkere_graaf(self):
        # Dit assert nu niks, maar deze method is wel een begin

        g = create_graph_helper(
            [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (5, 7), (5, 8), (3, 8), (3, 9), (1, 9), (2, 9),
             (1, 10), (6, 11), (7, 11), (11, 12), (11, 13), (11, 14), (12, 13), (12, 14), (13, 14)])

        h = g.deepcopy()

        md = graph_to_modules(g + h)
        graph_md, modular_iso = modules_to_graph_with_module_isomorphism(md)
 def test_has_same_color_neighbours(self):
     # 1 - 2 - 3 - 4
     #         |
     #         5
     g = tools.create_graph_helper([[1, 2], [2, 3], [3, 4], [3, 5]])
     v_g1, v_g2, v_g3, v_g4, v_g5 = g.vertices
     coloring = tests.create_coloring_helper_vertex({
         0: [v_g1],
         1: [v_g4, v_g5],
         2: [v_g2],
         3: [v_g3]
     })
     self.assertTrue(has_same_color_neighbours(v_g4, v_g5, coloring))
     self.assertFalse(has_same_color_neighbours(v_g1, v_g4, coloring))
    def test_modules_to_graph(self):
        tests.set_up_test_graphs()

        modules = graph_to_modules(tests.non_trivial_graph)
        graph, _ = modules_to_graph(modules)
        labels = [vertex.label for vertex in graph.vertices]
        expected_labels = ["0", "1", "2+4", "3"]
        self.assertTrue(set(labels) == set(expected_labels))

        modules = graph_to_modules(tests.modular_decomposition_graph)
        graph, _ = modules_to_graph(modules)
        labels = [vertex.label for vertex in graph.vertices]
        expected_labels = ["0+1+4", "2+3", "5+6"]
        self.assertTrue(set(labels) == set(expected_labels))

        modules = graph_to_modules(tests.butterfly)
        graph, _ = modules_to_graph(modules)
        labels = [vertex.label for vertex in graph.vertices]
        expected_labels = ["0", "1+4", "2+3"]
        self.assertTrue(set(labels) == set(expected_labels))

        modules2 = graph_to_modules(graph)
        graph2, _ = modules_to_graph(modules2)
        labels = [vertex.label for vertex in graph2.vertices]
        expected_labels = ["0", "1+4+2+3"]
        self.assertTrue(set(labels) == set(expected_labels))

        modules3 = graph_to_modules(graph2)
        graph3, _ = modules_to_graph(modules3)
        labels = [vertex.label for vertex in graph3.vertices]
        expected_labels = ["0+1+4+2+3"]
        self.assertTrue(set(labels) == set(expected_labels))

        modules4 = graph_to_modules(graph3)
        graph4, _ = modules_to_graph(modules4)
        labels = [vertex.label for vertex in graph4.vertices]
        expected_labels = ["0+1+4+2+3"]
        self.assertTrue(set(labels) == set(expected_labels))

        g = tools.create_graph_helper([[1, 2], [1, 3], [2, 3]])
        modules_triangle = graph_to_modules(g)
        graph, _ = modules_to_graph(modules_triangle)
        labels = [vertex.label for vertex in graph.vertices]
        expected_labels = ["1+2+3"]
        self.assertTrue(set(labels) == set(expected_labels))
Example #6
0
def modules_to_graph(
        modules: ModularDecomposition) -> (Graph, {
            Vertex: Vertex
        }):
    """
    Returns a new Graph object with Modules compressed to a Vertex
    :param modules: list of modules
    :return: new Graph
    """

    label_mapping = {}

    edges_list = []
    for module in modules:
        for vertex in module:
            edges_list += get_edges_of_vertex(vertex)

    for module in modules:
        if len(module) > 1:
            new_label = create_new_label(module)
            for vertex in module:
                label_mapping[vertex] = new_label
            edges_list = relabel_edges(module, edges_list, new_label)

    edges = set()
    for edge in edges_list:
        if edge[0] != edge[1]:
            edges.add(tuple(sorted(edge)))

    if not edges:
        graph = Graph(False)
        if edges_list:
            vertex = Vertex(graph, edges_list[0][0])
        graph.add_vertex(vertex)
    else:
        graph = create_graph_helper(sorted(list(edges)))

    old_new_vertex_mapping = {}
    for vertex, label in label_mapping.items():
        old_new_vertex_mapping[vertex] = graph.find_vertex(label)

    return graph, old_new_vertex_mapping
    def test_group_by(self):
        # group_by(List[int]) groups by number
        a = [1, 2, 3, 2, 3]
        expected = {1: [1], 2: [2, 2], 3: [3, 3]}
        self.assertEqual(expected, group_by(a))

        # group_by(List[Vertex], key=Vertex.degree)
        # 0 -- 1 -- 2
        #                7 -- 4
        #              /  \
        #             6 - 5
        #             \   /
        #               3
        g = tools.create_graph_helper([(0, 1), (1, 2), (4, 7), (3, 5), (3, 6),
                                       (5, 7), (6, 7), (5, 6)])
        vertices = sorted(g.vertices, key=lambda vertex: vertex.label)
        expected = {
            1: [vertices[0], vertices[2], vertices[4]],
            2: [vertices[1], vertices[3]],
            3: [vertices[5], vertices[6], vertices[7]]
        }
        actual = group_by(g.vertices, lambda v: v.degree)

        self.assertEqual(expected.keys(), actual.keys())
        for key in expected.keys():
            self.assertTrue(
                compare(expected[key], actual[key], lambda v: v.label))

        # group_by(dict{List}, key = lambda x: len(x)) groups by length of the lists
        degrees = {
            1: [vertices[0], vertices[2], vertices[4]],
            2: [vertices[1], vertices[3]],
            3: [vertices[5], vertices[6], vertices[7]]
        }
        expected = {2: [2], 3: [1, 3]}
        self.assertEqual(expected, group_by(degrees,
                                            lambda k: len(degrees[k])))

        # group by amount of neighbours with a given color
        # [x]: node with color/degree 1
        # [0] -- 1 -- [2]
        #                7 -- [4]
        #              /  \
        #             6 - 5
        #             \   /
        #               3
        degree_coloring = group_by(g.vertices, lambda v: v.degree)
        for c in degree_coloring:
            for v in degree_coloring[c]:
                v.colornum = c

        n_neighbors_of_color1 = group_by(
            vertices,
            lambda v: len([w for w in v.neighbours if w.colornum == 1]))
        expected = {
            0: [
                vertices[0], vertices[2], vertices[3], vertices[4],
                vertices[5], vertices[6]
            ],
            1: [vertices[7]],
            2: [vertices[1]]
        }

        self.assertEqual(expected.keys(), n_neighbors_of_color1.keys())
        for key in expected.keys():
            self.assertEqual(
                len(expected[key]), len(n_neighbors_of_color1[key]),
                "Expect key " + str(key) + ' to have ' +
                str(len(expected[key])) + ' vertices')
            self.assertTrue(
                compare(expected[key], n_neighbors_of_color1[key],
                        lambda v: v.label))
Example #8
0
def set_up_test_graphs():
    global empty_graph, connected_graph_order_2, disconnected_graph_order_2, non_trivial_graph, \
        non_trivial_graph_different_label, non_trivial_graph_different_weight, non_trivial_graph_complement, \
        isomorphic_graphs, anisomorphic_graphs, v4e4_connected, v5e4loop_unconnected, v5e7, v3e2_connected, \
        v5e4_connected, v8e7loop_unconnected, modular_decomposition_graph, butterfly, v8e7loop_unconnected2

    # Prepare some vertex labels for general use
    vertex_labels = ['spam', 'ham', 'eggs', 'foo', 'bar', 'baz', 'qux', 'quux', 'quuz', 'corge', 'grault', 'garply',
                     'waldo', 'fred', 'plugh', 'xyzzy', 'thud']

    # Instantiate the empty graph
    empty_graph = Graph(directed=False)

    # Instantiate a connected graph of order 2
    # connected_graph_order_2 =
    #     spam - ham
    connected_graph_order_2 = create_graph_helper([(vertex_labels[0], vertex_labels[1])])

    # Instantiate a non-trivial graph
    # non_trivial_graph =
    #           2
    #          / \
    #     0 - 1   3
    #          \ /
    #           4
    non_trivial_graph = create_graph_helper([(0, 1), (1, 2), (1, 4), (2, 3), (3, 4)])
    non_trivial_graph.name = 'non_trivial_graph'

    # Instantiate the non-trivial graph's complement
    # non_trivial_graph_complement =
    #               2
    #              / \
    #     1 - 3 - 0 - 4
    non_trivial_graph_complement = create_graph_helper([(2, 0), (3, 0), (4, 0), (3, 1), (4, 2)])
    non_trivial_graph_complement.name = 'non_trivial_graph_complement'

    # Instantiate some isomorphic graphs
    # iso_0 =
    #           - 0 -
    #          /     \
    #     3 - 4 - 1 - 5
    #          \     /
    #           - 2 -
    # iso_1 =
    #           - 2 -
    #          /     \
    #     3 - 4 - 0 - 5
    #          \     /
    #           - 1 -
    # iso_2 =
    #           - 1 -
    #          /     \
    #     3 - 4 - 2 - 5
    #          \     /
    #           - 0 -
    changing_labels = [0, 1, 2]
    isomorphic_graphs = []
    for _ in range(len(changing_labels)):  # Because changing_labels changes, this can't simply be changing_labels
        _0 = changing_labels[0]
        _1 = changing_labels[1]
        _2 = changing_labels[2]
        isomorphism = create_graph_helper([(3, 4), (4, _0), (_0, 5), (4, _1), (_1, 5), (4, _2), (_2, 5)])
        isomorphism.name = f'isomorphism_{_0}_{_1}_{_2}'
        isomorphic_graphs.append(isomorphism)
        changing_labels = [changing_labels.pop()] + changing_labels

    # Instantiate some anisomorphic graphs
    # anisomorphism_0 =
    #           - 4 -
    #          /  |  \
    #     3 - 0   1   2
    #          \  |  /
    #           - 5 -
    # anisomorphism_1 =
    #           - 4 -
    #          /  |  \
    #     3 - 0 - 1   2
    #          \     /
    #           - 5 -
    anisomorphism_0 = create_graph_helper([(3, 0), (0, 4), (4, 1), (4, 2), (0, 5), (1, 5), (2, 5)])
    anisomorphism_0.name = 'anisomorphism_0'
    anisomorphism_1 = create_graph_helper([(3, 0), (0, 4), (4, 1), (4, 2), (0, 5), (1, 0), (2, 5)])
    anisomorphism_1.name = 'anisomorphism_1'
    anisomorphic_graphs = [anisomorphism_0, anisomorphism_1]

    # Create a graph with 4 vertices and 4 edges with a cycle:
    # v4e4_connected =
    #         1 - 2 - 3
    #              \ /
    #               4
    v4e4_connected = create_graph_helper([(1, 2), (2, 3), (2, 4), (3, 4)])
    v4e4_connected.name = 'v4e4'

    # Create a graph with 5 vertices and 4 edges, including looped egde at vertex 4:
    # v5e4loop_unconnected =
    #         1 - 2 - 3   4=
    #                 |
    #                 5
    v5e4loop_unconnected = create_graph_helper([(1, 2), (2, 3), (3, 5), (4, 4)])
    v5e4loop_unconnected.name = 'v5e4_loop4'

    # Create a graph with 8 vertices and 7 edges, unconnected:
    #    # v8e7_unconnected =
    #         1 - 2 - 3   5 - 6  8=
    #                 |    \ /
    #                 4     7
    v8e7loop_unconnected = create_graph_helper([(1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (5, 7), (8, 8)])
    v8e7loop_unconnected.name = 'v8e7loop_unconnected'

    # Create a graph with 8 vertices and 7 edges, unconnected:
    #    # v8e7_unconnected2 =
    #         1 - 2 - 3   5 - 6  8=
    #                 |    \ /
    #                 4     7
    v8e7loop_unconnected2 = create_graph_helper([(1, 2), (2, 3), (3, 4), (5, 6), (6, 7), (5, 7), (8, 8)])
    v8e7loop_unconnected2.name = 'v8e7loop_unconnected2'

    # Create a graph where the complement should be taken during preprocessing :
    # v5e7 =
    #               5 --
    #              / \  \
    #         1 - 2 - 3 |
    #              \ /  /
    #               4 --
    v5e7 = create_graph_helper([(0, 3), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)])
    v5e7.name = 'v5e7'

    # Create a graph with 3 vertices and 2 edges :
    # v3e2_connected =
    #         1 - 2 - 3
    v3e2_connected = create_graph_helper([(1, 2), (2, 3)])
    v3e2_connected.name = 'v3e2_connected'

    # Create a tree graph with 5 vertices and 4 edges :
    # v5e4_connected =
    #         1 - 2 - 3 - 4
    #                 |
    #                 5
    v5e4_connected = create_graph_helper([(1, 2), (2, 3), (3, 5), (3, 4)])
    v5e4_connected.name = 'v5e4_connected'

    # Instantiate a graph with three modules
    modular_decomposition_graph = create_graph_helper(
        [(6, 1), (6, 0), (6, 4), (5, 1), (5, 0), (5, 4), (2, 1), (2, 0), (2, 4), (3, 1), (3, 0), (3, 4), (2, 3)]
    )

    # Instantiate a recursively modular decomposable graph
    butterfly = create_graph_helper([(0, 1), (0, 2), (0, 3), (0, 4), (1, 4), (2, 3)])