Exemple #1
0
    def __check_prod_input(graph, prod_input):
        assert len(prod_input) == 1
        i_id = prod_input[0]
        i_data = graph.nodes[i_id]
        i_layer = i_data['layer']

        assert i_data['label'] == 'I'

        i_neighbors = get_neighbors_at(graph, i_id, i_layer)
        assert len(i_neighbors) == 3

        nodes_with_other_neighbors = [
            e for e in i_neighbors
            if all(n not in i_neighbors
                   for n in get_neighbors_at(graph, e, i_layer))
        ]
        assert len(nodes_with_other_neighbors) == 1
        e1 = nodes_with_other_neighbors[0]
        (e2, e3) = [e for e in i_neighbors if e != e1]
        e12 = get_vertex_between(graph, e1, e2, i_layer, 'E')
        e13 = get_vertex_between(graph, e1, e3, i_layer, 'E')
        assert e12 is not None
        assert e13 is not None

        cycle_list = [e3, e13, e1, e12, e2]
        for i, e in enumerate(cycle_list):
            assert graph.nodes[e]['label'] == 'E'
            prev_e = cycle_list[(i - 1) % len(cycle_list)]
            next_e = cycle_list[(i + 1) % len(cycle_list)]
            assert all(n in get_neighbors_at(graph, e, i_layer)
                       for n in [prev_e, next_e])

        return e1, e2, e3, e12, e13
Exemple #2
0
    def test_happy_path(self):
        graph = Graph()
        e1 = gen_name()
        e2 = gen_name()
        e3 = gen_name()
        graph.add_node(e1, layer=1, position=(1.0, 2.0), label='E')
        graph.add_node(e2, layer=1, position=(1.0, 1.0), label='E')
        graph.add_node(e3, layer=1, position=(2.0, 1.0), label='E')

        graph.add_edge(e1, e2)
        graph.add_edge(e1, e3)
        graph.add_edge(e2, e3)

        i = add_interior(graph, e1, e2, e3)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        [i1] = P9().apply(graph, [i])

        # if correct number of nodes and edges
        self.assertEqual(len(graph.nodes()), 8)
        self.assertEqual(len(graph.edges()), 13)

        # if cross-layer interior connections
        self.assertEqual(graph.nodes[i]['label'], 'i')
        self.assertTrue(graph.has_edge(i, i1))

        # if new interior has correct label and layer
        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1)

        # if new interior has 3 neighbors
        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)

        # if new nodes are in correct positions
        new_e1 = get_node_at(graph, 2, (1.0, 2.0))
        new_e2 = get_node_at(graph, 2, (1.0, 1.0))
        new_e3 = get_node_at(graph, 2, (2.0, 1.0))
        self.assertIsNotNone(new_e1)
        self.assertIsNotNone(new_e2)
        self.assertIsNotNone(new_e3)

        # if each vertex has correct label
        for n in i1_neighbors:
            self.assertEqual(graph.nodes[n]['label'], 'E')

        # if each vertex has correct number of neighbors
        for n in i1_neighbors:
            node_neighbors = get_neighbors_at(graph, n,
                                              graph.nodes[n]['layer'])
            self.assertEqual(len(node_neighbors), 3)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
Exemple #3
0
    def check_graph_integrity(self, graph, i_node_id, expected_label):
        i_node_data = graph.nodes[i_node_id]
        i_node_layer = i_node_data['layer']

        self.assertEqual(i_node_data['label'], expected_label)

        neighbors = get_neighbors_at(graph, i_node_id, i_node_layer)
        self.assertEqual(len(neighbors), 3)
        for n_id in neighbors:
            self.assertEqual(graph.nodes[n_id]['label'], 'E')
            n_expected_neighbors = [x for x in neighbors if x != n_id]
            n_neighbors = get_neighbors_at(graph, n_id, i_node_layer)
            for expected_neighbor in n_expected_neighbors:
                self.assertTrue(expected_neighbor in n_neighbors)
Exemple #4
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:
        [i] = prod_input
        i_data = graph.nodes[i]
        self.__check_prod_input(graph, prod_input)

        i_data['label'] = 'i'
        i_layer = i_data['layer']
        new_layer = i_layer + 1

        i_neighbors = get_neighbors_at(graph, i, i_layer)

        # e1 doesn't mean e1 with (x1, y1)
        vx_e1 = gen_name()
        vx_e2 = gen_name()
        vx_e3 = gen_name()

        e1_pos = graph.nodes[i_neighbors[0]]['position']
        e2_pos = graph.nodes[i_neighbors[1]]['position']
        e3_pos = graph.nodes[i_neighbors[2]]['position']

        graph.add_node(vx_e1, layer=new_layer, position=e1_pos, label='E')
        graph.add_node(vx_e2, layer=new_layer, position=e2_pos, label='E')
        graph.add_node(vx_e3, layer=new_layer, position=e3_pos, label='E')

        graph.add_edge(vx_e1, vx_e2)
        graph.add_edge(vx_e2, vx_e3)
        graph.add_edge(vx_e3, vx_e1)

        sorted_segments = sort_segments_by_angle(graph, [(vx_e1, vx_e2),
                                                         (vx_e2, vx_e3),
                                                         (vx_e3, vx_e1)])
        segment_to_break = sorted_segments[orientation % 3]
        b = add_break_in_segment(graph, segment_to_break)
        b_neighbors = get_neighbors_at(graph, b, i_layer + 1)
        remaining = [x for x in [vx_e1, vx_e2, vx_e3]
                     if x not in b_neighbors][0]
        graph.add_edge(b, remaining)

        i1 = add_interior(graph, b_neighbors[0], b, remaining)
        i2 = add_interior(graph, b_neighbors[1], b, remaining)

        graph.add_edge(i1, i)
        graph.add_edge(i2, i)

        return [i1, i2]
Exemple #5
0
    def __check_prod_input(graph, prod_input):
        i_node_id = prod_input[0]
        i_node_data = graph.nodes[i_node_id]
        i_node_layer = i_node_data['layer']

        assert i_node_data['label'] == 'I'

        neighbors = get_neighbors_at(graph, i_node_id, i_node_layer)
        assert len(neighbors) == 3
        for n_id in neighbors:
            assert graph.nodes[n_id]['label'] == 'E'
            n_expected_neighbors = [x for x in neighbors if x != n_id]
            n_neighbors = get_neighbors_at(graph, n_id, i_node_layer)
            for expected_neighbor in n_expected_neighbors:
                assert expected_neighbor in n_neighbors
Exemple #6
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:

        self.__check_prod_input(graph, prod_input)

        overlapping_vertices = find_overlapping_vertices(graph)[0]
        layer = graph.nodes()[prod_input[0]]['layer']

        neighbours = set()
        for interior in prod_input:
            neighbours |= set(get_neighbors_at(graph, interior, layer))

        vertices_to_join = [
            neighbour for neighbour in neighbours if graph.nodes()[neighbour]
            ['position'] == graph.nodes()[overlapping_vertices[0]]['position']
        ]

        if len(vertices_to_join) == 2:
            join_overlapping_vertices(graph, vertices_to_join[0],
                                      vertices_to_join[1], layer)

        return prod_input
Exemple #7
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:
        # Production based on P6
        prod_input = self.__sort_prod_input(graph, prod_input)
        self.__check_prod_input(graph, prod_input)

        up_layer = graph.nodes()[prod_input[0]]['layer']
        down_layer = graph.nodes()[prod_input[3]]['layer']
        v1_up, v2_up = get_common_neighbors(graph, prod_input[0],
                                            prod_input[1], up_layer)
        pos_v1 = graph.nodes()[v1_up]['position']
        pos_v2 = graph.nodes()[v2_up]['position']

        to_merge = [[], []]
        for interior in prod_input[2:]:
            for v in get_neighbors_at(graph, interior, down_layer):
                if graph.nodes()[v]['position'] == pos_v1:
                    to_merge[0].append(v)
                elif graph.nodes()[v]['position'] == pos_v2:
                    to_merge[1].append(v)

        for v1, v2 in to_merge:
            join_overlapping_vertices(graph, v1, v2, down_layer)

        return []
Exemple #8
0
    def __check_prod_input(graph, prod_input, eps):
        assert len(prod_input) == 1
        i_node_id = prod_input[0]
        i_node_data = graph.nodes[i_node_id]
        i_node_layer = i_node_data['layer']

        assert i_node_data['label'] == 'I'

        neighbours = get_neighbors_at(graph, i_node_id, i_node_layer)
        assert len(neighbours) == 3

        for n_id in neighbours:
            assert graph.nodes[n_id]['label'] == 'E'

        for e1, e2 in zip(neighbours, neighbours[1:] + neighbours[:1]):
            # find common 'E' neighbours in the same layer and exactly in the middle of e1_e2 segment
            (e1_x, e1_y) = graph.nodes[e1]['position']
            (e2_x, e2_y) = graph.nodes[e2]['position']
            middle_position = ((e1_x + e2_x) / 2, (e1_y + e2_y) / 2)
            common_neighbours = [n for n in graph.neighbors(e1)
                                 if n in graph.neighbors(e2)
                                 and graph.nodes[n]['layer'] == i_node_layer
                                 and graph.nodes[n]['label'] == 'E'
                                 and P5.is_close(graph.nodes[n]['position'], middle_position, eps)]
            assert len(common_neighbours) == 1
Exemple #9
0
    def __check_prod_input(graph, prod_input):
        if len(prod_input) != 1:
            raise ValueError('wrong number of interiors')
        i_node_id = prod_input[0]
        i_node_data = graph.nodes[i_node_id]
        i_node_layer = i_node_data['layer']

        if i_node_data['label'] != 'I':
            raise ValueError("wrong interior label")

        neighbors = get_neighbors_at(graph, i_node_id, i_node_layer)
        if len(neighbors) != 3:
            raise ValueError("interior with wrong number of edges")

        for n_id in neighbors:
            if graph.nodes[n_id]['label'] != 'E':
                raise ValueError("wrong vertex label")
            n_expected_neighbors = [x for x in neighbors if x != n_id]
            n_neighbors = get_neighbors_at(graph, n_id, i_node_layer)
            for expected_neighbor in n_expected_neighbors:
                if expected_neighbor not in n_neighbors:
                    raise ValueError("missing edge between vertices")
Exemple #10
0
        def check_structure(interior_nodes, layer_num):
            for interior_node in interior_nodes:
                neighbours = get_neighbors_at(graph, interior_node, layer_num)
                if len(neighbours) > 3:
                    raise ValueError(
                        'Wrong number of neighbours of an interior vertex')
                for n in neighbours:
                    if graph.nodes()[n]['label'] != "E":
                        raise ValueError('Vertex does not have "E" label')

            common_neighbors = get_common_neighbors(graph, interior_nodes[0],
                                                    interior_nodes[1],
                                                    layer_num)
            if len(common_neighbors) > 2:
                raise ValueError('Interiors have more than 2 common neighbors')

            return common_neighbors
Exemple #11
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:
        """
        Apply 6th production on graph

        `prod_input` is list of 6 interiors as follows: `[upper, upper, lower, lower, lower, lower]`,
        where `upper` is vertex on upper layer and `lower` on lower layer. Order of vertices in one
        layer is irrelevant.

        `orientation` and `**kwargs` are ignored

        Returns empty list, as no new vertices were added.
        """

        self.__check_prod_input(graph, prod_input)

        up_layer = graph.nodes()[prod_input[0]]['layer']
        down_layer = graph.nodes()[prod_input[2]]['layer']
        v1_up, v2_up = get_common_neighbors(graph, prod_input[0],
                                            prod_input[1], up_layer)
        pos_v1 = graph.nodes()[v1_up]['position']
        pos_v2 = graph.nodes()[v2_up]['position']

        x = (pos_v1[0] + pos_v2[0]) / 2
        y = (pos_v1[1] + pos_v2[1]) / 2
        pos_center = (x, y)

        to_merge = [[], [], []]
        for interior in prod_input[2:]:
            for v in get_neighbors_at(graph, interior, down_layer):
                if graph.nodes()[v]['position'] == pos_v1:
                    to_merge[0].append(v)
                elif graph.nodes()[v]['position'] == pos_v2:
                    to_merge[1].append(v)
                elif graph.nodes()[v]['position'] == pos_center:
                    if v not in to_merge[2]:
                        to_merge[2].append(v)

        for v1, v2 in to_merge:
            join_overlapping_vertices(graph, v1, v2, down_layer)

        return []
Exemple #12
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:
        # Production based on P2
        self.__check_prod_input(graph, prod_input)

        [i] = prod_input
        i_data = graph.nodes[i]
        i_data['label'] = 'i'
        i_layer = i_data['layer']
        new_layer = i_layer + 1

        i_neighbors = get_neighbors_at(graph, i, i_layer)

        # create new 'E' nodes in the next layer
        new_e1 = gen_name()
        new_e2 = gen_name()
        new_e3 = gen_name()

        e1_pos = graph.nodes[i_neighbors[0]]['position']
        e2_pos = graph.nodes[i_neighbors[1]]['position']
        e3_pos = graph.nodes[i_neighbors[2]]['position']

        graph.add_node(new_e1, layer=new_layer, position=e1_pos, label='E')
        graph.add_node(new_e2, layer=new_layer, position=e2_pos, label='E')
        graph.add_node(new_e3, layer=new_layer, position=e3_pos, label='E')

        # create edges between new 'E' nodes
        graph.add_edge(new_e1, new_e2)
        graph.add_edge(new_e2, new_e3)
        graph.add_edge(new_e3, new_e1)

        # create new 'I' node and edges between new 'I' nodes and new 'E' nodes
        i1 = add_interior(graph, new_e1, new_e2, new_e3)

        # create edges between new 'I' node and parent 'i' node
        graph.add_edge(i1, i)

        return [i1]
Exemple #13
0
    def get_corner_nodes(graph, i, i_layer, orientation):
        """
        Get 'E' nodes that are neighbours of 'I' node at i_layer level.
        Order of returned nodes is not random. Methods returns nodes e1, e2 and e3 in counterclockwise order. Moreover
        we assume that the triangle will be cut into half by a segment from e2 to point in the middle of e1_e3 segment.
        If orientation is 0, method will assume that the longest segment is divided in half. If not, the segment is
        chosen by switching segment 'orientation' times in counterclockwise direction.
        """

        [a, b, c] = get_neighbors_at(graph, i, i_layer)

        # find counterclockwise order of nodes
        (a_x, a_y) = graph.nodes[a]['position']
        (b_x, b_y) = graph.nodes[b]['position']
        (c_x, c_y) = graph.nodes[c]['position']

        m = P5.calc_mean(a_x, a_y, b_x, b_y, c_x, c_y)

        ma_angle = angle_with_x_axis(m, (a_x, a_y))
        mb_angle = angle_with_x_axis(m, (b_x, b_y))
        mc_angle = angle_with_x_axis(m, (c_x, c_y))

        angles_counterclockwise = sorted([(a, ma_angle), (b, mb_angle), (c, mc_angle)], key=lambda p: p[1])
        nodes_counterclockwise = [p[0] for p in angles_counterclockwise]

        # find longest edge
        ab = P5.calc_distance_between(graph, a, b)
        bc = P5.calc_distance_between(graph, b, c)
        ca = P5.calc_distance_between(graph, c, a)

        if max(ab, bc, ca) == ab:
            middle_offset = nodes_counterclockwise.index(c)
        elif max(ab, bc, ca) == bc:
            middle_offset = nodes_counterclockwise.index(a)
        else:
            middle_offset = nodes_counterclockwise.index(b)

        offset = (orientation + (1 - middle_offset)) % 3

        return nodes_counterclockwise[offset:] + nodes_counterclockwise[:offset]  # rotate table according to offset
Exemple #14
0
    def __check_prod_input(graph, prod_input):

        if len(set(prod_input)) != 4:
            raise ValueError('too few interiors')
        layer = graph.nodes()[prod_input[0]]['layer']
        if any(graph.nodes()[interior]['layer'] != layer
               for interior in prod_input[1:]):
            raise ValueError('interior vertices come from different layers')
        if any(graph.nodes()[interior]['label'] != 'I'
               for interior in prod_input):
            raise ValueError('interior vertices must have I label')

        all_neighbours = []

        for interior in prod_input:
            interior_neighbours = get_neighbors_at(graph, interior, layer)
            if len(interior_neighbours) != 3:
                raise ValueError('wrongly connected interior vertices')

            for neighbour in interior_neighbours:
                if graph.nodes()[neighbour]['label'] != 'E':
                    raise ValueError(
                        'interior vertices can be connect only with E vertices'
                    )

                all_neighbours.append(neighbour)

        if len(set(all_neighbours)) != 6:
            raise ValueError('incorrect number of E vertices')

        overlapping_vertices = find_overlapping_vertices(graph)

        if len(overlapping_vertices) != 2 or \
                any(overlapping_vertice1 not in set(all_neighbours)
                    or overlapping_vertice2 not in set(all_neighbours)
                    for overlapping_vertice1, overlapping_vertice2 in overlapping_vertices):
            raise ValueError('incorrect shape of graph')
Exemple #15
0
    def test_happy_path(self):
        graph = Graph()
        e1 = gen_name()
        e2 = gen_name()
        e3 = gen_name()
        e4 = gen_name()
        e1_1 = gen_name()
        e1_2 = gen_name()
        e1_3 = gen_name()
        e2_1 = gen_name()
        e2_2 = gen_name()
        e2_4 = gen_name()
        e3_5 = gen_name()

        graph.add_node(e1, layer=1, position=(1.0, 1.0), label='E')
        graph.add_node(e2, layer=1, position=(2.0, 2.0), label='E')
        graph.add_node(e3, layer=1, position=(1.0, 2.0), label='E')
        graph.add_node(e4, layer=1, position=(2.0, 1.0), label='E')
        graph.add_node(e1_1, layer=2, position=(1.0, 1.0), label='E')
        graph.add_node(e1_2, layer=2, position=(2.0, 2.0), label='E')
        graph.add_node(e1_3, layer=2, position=(1.0, 2.0), label='E')
        graph.add_node(e2_1, layer=2, position=(1.0, 1.0), label='E')
        graph.add_node(e2_2, layer=2, position=(2.0, 2.0), label='E')
        graph.add_node(e2_4, layer=2, position=(2.0, 1.0), label='E')
        graph.add_node(e3_5, layer=2, position=(2.0, 3.0), label='E')

        graph.add_edge(e1, e2)
        graph.add_edge(e1, e3)
        graph.add_edge(e1, e4)
        graph.add_edge(e2, e3)
        graph.add_edge(e2, e4)
        graph.add_edge(e1_1, e1_2)
        graph.add_edge(e1_1, e1_3)
        graph.add_edge(e1_2, e1_3)
        graph.add_edge(e2_1, e2_2)
        graph.add_edge(e2_1, e2_4)
        graph.add_edge(e2_2, e2_4)
        graph.add_edge(e3_5, e1_2)
        graph.add_edge(e3_5, e1_3)

        i1 = add_interior(graph, e1, e2, e3)
        i2 = add_interior(graph, e1, e2, e4)
        i1_1 = add_interior(graph, e1_1, e1_2, e1_3)
        i2_1 = add_interior(graph, e2_1, e2_2, e2_4)
        i3_1 = add_interior(graph, e3_5, e1_2, e1_3)
        graph.nodes[i1]['label'] = 'i'
        graph.nodes[i2]['label'] = 'i'

        graph.add_edge(i1, i1_1)
        graph.add_edge(i2, i2_1)
        graph.add_edge(i1, i3_1)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        P12().apply(graph, [i1, i2, i1_1, i2_1])

        # if correct number of nodes and edges
        self.assertEqual(len(graph.nodes()), 14)
        self.assertEqual(len(graph.edges()), 30)

        # if interiors has correct labels, layers and are connected
        self.assertEqual(graph.nodes[i1]['label'], 'i')
        self.assertEqual(graph.nodes[i2]['label'], 'i')
        self.assertEqual(graph.nodes[i1_1]['label'], 'I')
        self.assertEqual(graph.nodes[i2_1]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], 1)
        self.assertEqual(graph.nodes[i2]['layer'], 1)
        self.assertEqual(graph.nodes[i1_1]['layer'], 2)
        self.assertEqual(graph.nodes[i2_1]['layer'], 2)
        self.assertTrue(graph.has_edge(i1, i1_1))
        self.assertTrue(graph.has_edge(i2, i2_1))

        # if each interior has 3 neighbors
        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer'])
        self.assertEqual(len(i2_neighbors), 3)
        i1_1_neighbors = get_neighbors_at(graph, i1_1,
                                          graph.nodes[i1_1]['layer'])
        self.assertEqual(len(i1_1_neighbors), 3)
        i2_1_neighbors = get_neighbors_at(graph, i2_1,
                                          graph.nodes[i2_1]['layer'])
        self.assertEqual(len(i2_1_neighbors), 3)

        # if nodes in lower layer exists and are correctly connected
        new_e1 = get_node_at(graph, 2, (1.0, 1.0))
        new_e2 = get_node_at(graph, 2, (2.0, 2.0))
        new_e3 = get_node_at(graph, 2, (1.0, 2.0))
        new_e4 = get_node_at(graph, 2, (2.0, 1.0))
        self.assertIsNotNone(new_e1)
        self.assertIsNotNone(new_e2)
        self.assertIsNotNone(new_e3)
        self.assertIsNotNone(new_e4)
        self.assertTrue(graph.has_edge(new_e1, new_e2))
        self.assertTrue(graph.has_edge(new_e1, new_e3))
        self.assertTrue(graph.has_edge(new_e1, new_e4))
        self.assertTrue(graph.has_edge(new_e2, new_e3))
        self.assertTrue(graph.has_edge(new_e2, new_e4))

        # if lower interiors connect with all 4 vertices
        all_neighbors = i1_1_neighbors + i2_1_neighbors
        all_neighbors = list(dict.fromkeys(all_neighbors))  # remove duplicates
        self.assertEqual(len(all_neighbors), 4)

        # if each vertex has correct label
        for n in all_neighbors:
            self.assertEqual(graph.nodes[n]['label'], 'E')

        # if each vertex has correct number of neighbors (based on neighbour interiors count)
        for n in all_neighbors:
            node_neighbors = get_neighbors_at(graph, n,
                                              graph.nodes[n]['layer'])
            i_neighbors = [
                x for x in node_neighbors if graph.nodes[x]['label'] == 'I'
            ]
            if len(i_neighbors) == 1:
                self.assertEqual(len(node_neighbors), 3)
            elif len(i_neighbors) == 2:
                self.assertEqual(len(node_neighbors), 5)
            else:
                self.assertEqual(len(node_neighbors), 7)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
    def test_risky_triangle_break(self):
        graph = Graph()
        e1, e2, e3, e4, e5 = [gen_name() for _ in range(5)]
        e6 = gen_name()

        graph.add_node(e1, layer=1, position=(1.0, 2.0), label='E')
        graph.add_node(e2, layer=1, position=(1.0, 1.5), label='E')
        graph.add_node(e3, layer=1, position=(1.0, 1.0), label='E')
        graph.add_node(e4, layer=1, position=(2.0, 1.0), label='E')
        graph.add_node(e5, layer=1, position=(1.5, 1.5), label='E')
        graph.add_node(e6, layer=1, position=(0.0, 1.5), label='E')

        graph.add_edge(e1, e2)
        graph.add_edge(e2, e3)
        graph.add_edge(e3, e4)
        graph.add_edge(e4, e5)
        graph.add_edge(e5, e1)

        graph.add_edge(e1, e6)
        graph.add_edge(e6, e3)

        i = add_interior(graph, e1, e3, e4)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        [i1, i2, i3] = P4().apply(graph, [i])

        self.assertEqual(len(graph.nodes()), 15)
        self.assertEqual(len(graph.edges()), 29)

        self.assertEqual(graph.nodes[i]['label'], 'i')
        self.assertTrue(graph.has_edge(i, i1))
        self.assertTrue(graph.has_edge(i, i2))
        self.assertTrue(graph.has_edge(i, i3))

        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i2]['label'], 'I')
        self.assertEqual(graph.nodes[i3]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i2]['layer'], graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i3]['layer'], graph.nodes[i]['layer'] + 1)

        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer'])
        self.assertEqual(len(i2_neighbors), 3)
        i3_neighbors = get_neighbors_at(graph, i3, graph.nodes[i3]['layer'])
        self.assertEqual(len(i3_neighbors), 3)

        i1_i2_n = [x for x in i1_neighbors if x in i2_neighbors]
        i1_i3_n = [x for x in i1_neighbors if x in i3_neighbors]
        i2_i3_n = [x for x in i2_neighbors if x in i3_neighbors]

        # Test i1-only neighbors
        for n in [
                x for x in i1_neighbors
                if x not in i1_i2_n and x not in i1_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test i2-only neighbors
        for n in [
                x for x in i2_neighbors
                if x not in i1_i2_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i2]['layer'])))

        # Test i3-only neighbors
        for n in [
                x for x in i3_neighbors
                if x not in i1_i3_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i3]['layer'])))

        # Test nodes connected to 2 interiors
        for n in [x for x in i1_i2_n if x not in i1_i3_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i1_i3_n if x not in i1_i2_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i2_i3_n if x not in i1_i2_n and x not in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test nodes connected to 3 interiors
        for n in [x for x in i2_i3_n if x in i1_i2_n and x in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                7, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
Exemple #17
0
    def test_happy_path(self):
        graph = Graph()
        e1 = gen_name()
        e2 = gen_name()
        e3 = gen_name()
        graph.add_node(e1, layer=0, position=(1.0, 2.0), label='E')
        graph.add_node(e2, layer=0, position=(1.0, 1.0), label='E')
        graph.add_node(e3, layer=0, position=(2.0, 1.0), label='E')

        graph.add_edge(e1, e2)
        graph.add_edge(e1, e3)
        graph.add_edge(e2, e3)

        i = add_interior(graph, e1, e2, e3)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        [i1, i2] = P2().apply(graph, [i])

        self.assertIsNotNone(get_node_at(graph, 1, (1.0, 2.0)))
        self.assertIsNotNone(get_node_at(graph, 1, (1.0, 1.0)))
        self.assertIsNotNone(get_node_at(graph, 1, (2.0, 1.0)))
        self.assertIsNotNone(get_node_at(graph, 1, (1.5, 1.0)))

        (i1_x, i1_y) = graph.nodes[i1]['position']
        (i2_x, i2_y) = graph.nodes[i2]['position']
        self.assertTrue(isclose(i1_x, 1.166666, rel_tol=eps))
        self.assertTrue(isclose(i1_y, 1.333333, rel_tol=eps))
        self.assertTrue(isclose(i2_x, 1.5, rel_tol=eps))
        self.assertTrue(isclose(i2_y, 1.333333, rel_tol=eps))

        self.assertEqual(len(graph.nodes()), 10)
        self.assertEqual(len(graph.edges()), 19)

        self.assertEqual(graph.nodes[i]['label'], 'i')
        self.assertTrue(graph.has_edge(i, i1))
        self.assertTrue(graph.has_edge(i, i2))

        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i2]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i2]['layer'], graph.nodes[i]['layer'] + 1)

        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer'])
        self.assertEqual(len(i2_neighbors), 3)

        common_neighbors = [x for x in i1_neighbors if x in i2_neighbors]

        for n in i1_neighbors:
            if n not in common_neighbors:
                self.assertEqual(graph.nodes[n]['label'], 'E')
                self.assertEqual(
                    len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])),
                    3)

        for n in i2_neighbors:
            if n not in common_neighbors:
                self.assertEqual(graph.nodes[n]['label'], 'E')
                self.assertEqual(
                    len(get_neighbors_at(graph, n, graph.nodes[i2]['layer'])),
                    3)

        for c_neighbor in common_neighbors:
            self.assertEqual(graph.nodes[c_neighbor]['label'], 'E')
            self.assertEqual(
                len(
                    get_neighbors_at(graph, c_neighbor,
                                     graph.nodes[i1]['layer'])), 5)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
    def test_in_bigger_graph(self):
        graph = Graph()

        # Base nodes
        e1, e2, e3, e4, e5 = [gen_name() for _ in range(5)]

        # Additional nodes
        e6, e7, e8, e9 = [gen_name() for _ in range(4)]

        graph.add_node(e1, layer=1, position=(1.0, 2.0), label='E')
        graph.add_node(e2, layer=1, position=(1.0, 1.5), label='E')
        graph.add_node(e3, layer=1, position=(1.0, 1.0), label='E')
        graph.add_node(e4, layer=1, position=(2.0, 1.0), label='E')
        graph.add_node(e5, layer=1, position=(1.5, 1.5), label='E')

        graph.add_node(e6, layer=1, position=(2.0, 2.0), label='E')
        graph.add_node(e7, layer=1, position=(1.0, 0.0), label='E')
        graph.add_node(e8, layer=1, position=(2.0, 0.0), label='E')
        graph.add_node(e9, layer=1, position=(1.5, -1.0), label='E')

        graph.add_edge(e1, e2)
        graph.add_edge(e2, e3)
        graph.add_edge(e3, e4)
        graph.add_edge(e4, e5)
        graph.add_edge(e5, e1)

        graph.add_edge(e1, e6)
        graph.add_edge(e6, e5)

        graph.add_edge(e7, e3)
        graph.add_edge(e7, e8)
        graph.add_edge(e7, e9)

        graph.add_edge(e8, e4)
        graph.add_edge(e8, e9)

        I = add_interior(graph, e1, e3, e4)
        I1 = add_interior(graph, e1, e5, e6)
        I2 = add_interior(graph, e7, e8, e4)
        I3 = add_interior(graph, e7, e8, e9)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        [i1, i2, i3] = P4().apply(graph, [I])

        self.assertEqual(len(graph.nodes()), 21)
        self.assertEqual(len(graph.edges()), 43)

        self.assertEqual(graph.nodes[I]['label'], 'i')
        self.assertTrue(graph.has_edge(I, i1))
        self.assertTrue(graph.has_edge(I, i2))
        self.assertTrue(graph.has_edge(I, i3))

        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i2]['label'], 'I')
        self.assertEqual(graph.nodes[i3]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[I]['layer'] + 1)
        self.assertEqual(graph.nodes[i2]['layer'], graph.nodes[I]['layer'] + 1)
        self.assertEqual(graph.nodes[i3]['layer'], graph.nodes[I]['layer'] + 1)

        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer'])
        self.assertEqual(len(i2_neighbors), 3)
        i3_neighbors = get_neighbors_at(graph, i3, graph.nodes[i3]['layer'])
        self.assertEqual(len(i3_neighbors), 3)

        i1_i2_n = [x for x in i1_neighbors if x in i2_neighbors]
        i1_i3_n = [x for x in i1_neighbors if x in i3_neighbors]
        i2_i3_n = [x for x in i2_neighbors if x in i3_neighbors]

        # Test i1-only neighbors
        for n in [
                x for x in i1_neighbors
                if x not in i1_i2_n and x not in i1_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test i2-only neighbors
        for n in [
                x for x in i2_neighbors
                if x not in i1_i2_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i2]['layer'])))

        # Test i3-only neighbors
        for n in [
                x for x in i3_neighbors
                if x not in i1_i3_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i3]['layer'])))

        # Test nodes connected to 2 interiors
        for n in [x for x in i1_i2_n if x not in i1_i3_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i1_i3_n if x not in i1_i2_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i2_i3_n if x not in i1_i2_n and x not in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test nodes connected to 3 interiors
        for n in [x for x in i2_i3_n if x in i1_i2_n and x in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                7, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
Exemple #19
0
    def __check_prod_input(graph: Graph, prod_input: List[str]):

        # Check number of vertices delivered
        if len(set(prod_input)) != 4:
            raise ValueError('Wrong number of interiors')

        # Check layers
        layers = []
        for interior in prod_input:
            layers.append(graph.nodes()[interior]['layer'])

        if layers[0] + 1 != layers[3]:
            raise ValueError('Interiors on wrong number of layers')
        if layers[0] != layers[1]:
            raise ValueError('Too few interiors in upper layer')
        if layers[2] != layers[3]:
            raise ValueError('Too few interiors in lower layer')
        up_layer = layers[0]
        down_layer = layers[3]

        # Check delivered vertices labels
        if any(graph.nodes()[interior]['label'] != 'i'
               for interior in prod_input[:2]):
            raise ValueError('Wrong label of vertices in upper layer')
        if any(graph.nodes()[interior]['label'] != 'I'
               for interior in prod_input[2:]):
            raise ValueError('Wrong label of vertices in lower layer')

        # Check connections between delivered vertices
        neighbors_in_lower_layer = {prod_input[0]: set(), prod_input[1]: set()}
        for upper_interior in prod_input[:2]:
            for bottom_neighbor in get_neighbors_at(graph, upper_interior,
                                                    down_layer):
                neighbors_in_lower_layer[upper_interior].add(bottom_neighbor)
        for lower_interior in prod_input[2:]:
            if lower_interior not in neighbors_in_lower_layer[prod_input[0]]\
              and lower_interior not in neighbors_in_lower_layer[prod_input[1]]:
                raise ValueError('Upper interiors not connected to lower ones')

        # maps lower interiors to its parent in upper layer
        lower_to_upper = dict()
        for upper in neighbors_in_lower_layer:
            for lower in neighbors_in_lower_layer[upper]:
                lower_to_upper[lower] = upper

        # Check common neighbors of upper interiors
        upper_neighbors = get_common_neighbors(graph, prod_input[0],
                                               prod_input[1], up_layer)
        if len(upper_neighbors) != 2:
            raise ValueError('Upper interiors don not have 2 common neighbors')

        # Get those neighbors and their positions as well as center position between them
        v1_up, v2_up = upper_neighbors
        pos_v1 = graph.nodes()[v1_up]['position']
        pos_v2 = graph.nodes()[v2_up]['position']

        # Check if they are connected
        if not graph.has_edge(v1_up, v2_up):
            raise ValueError('Upper vertices are not connected')

        # Prepare list of vertices in lower layer
        pairs_of_lower = [set(), set()]
        for interior in prod_input[2:]:
            for v in get_neighbors_at(graph, interior, down_layer):
                if graph.nodes()[v]['position'] == pos_v1:
                    pairs_of_lower[0].add((v, lower_to_upper[interior]))
                elif graph.nodes()[v]['position'] == pos_v2:
                    pairs_of_lower[1].add((v, lower_to_upper[interior]))

        # Check if pair is indeed pair of vertices
        for pair in pairs_of_lower:
            s = set(map(lambda x: x[0], pair))
            if len(s) != 2:
                raise ValueError(
                    'Connections between lower vertices are incorrect')

        # separate vertices based on side it is on (vertices on one side are connected)
        vertices_by_side = {prod_input[0]: list(), prod_input[1]: list()}
        for pair in pairs_of_lower:
            for v in pair:
                vertices_by_side[v[1]].append(v[0])
        # Now vertices_by_side should be dict where keys are id's of interiors in upper layer
        # and values are lists of vertices in lower layer on belonging to this parent

        # Check if vertices on opposite sides are connected
        # (they obviously shouldn't be right?)
        for v in vertices_by_side[prod_input[0]]:
            if any(
                    graph.has_edge(v, v_other)
                    for v_other in vertices_by_side[prod_input[1]]):
                raise ValueError(
                    'Connections between lower vertices are incorrect')

        # Check if labels are E
        all_vertices = vertices_by_side[prod_input[0]] + vertices_by_side[
            prod_input[1]] + [v1_up, v2_up]
        if any(graph.nodes()[v]['label'] != 'E' for v in all_vertices):
            raise ValueError('Not all vertices have label E')
    def test_parent_graph(self):
        graph = Graph()
        positions = [(1.0, 1.0), (1.0, 9.0), (9.0, 1.0), (9.0, 9.0),
                     (5.0, 5.0), (3.0, 7.0), (7.0, 7.0), (6.0, 6.0),
                     (4.0, 8.0)]

        [e0a, e1, e0b, e0c, e2, e12, e3, e23,
         e31] = self.create_nodes(graph, 1, 'E', positions)

        self.create_edges_chain(graph, [e0a, e1, e12, e0a, e2, e12])
        self.create_edges_chain(graph, [e0a, e0b, e2, e23, e0b, e3, e23])
        self.create_edges_chain(graph, [e0b, e0c, e3, e31, e0c, e1, e31])

        i_0a_1_12 = add_interior(graph, e0a, e1, e12)
        i_0a_12_2 = add_interior(graph, e0a, e12, e2)
        i_0a_0b_2 = add_interior(graph, e0a, e0b, e2)
        i_0b_2_23 = add_interior(graph, e0b, e2, e23)
        i_0b_23_3 = add_interior(graph, e0b, e23, e3)
        i_0b_0c_3 = add_interior(graph, e0b, e3, e0c)
        i_0c_1_31 = add_interior(graph, e1, e31, e0c)
        i_0c_3_31 = add_interior(graph, e31, e3, e0c)
        i = add_interior(graph, e1, e2, e3)

        if visualize_tests:
            pyplot.title("Correct subgraph input", fontsize=16)
            visualize_graph_layer(graph, 1)
            pyplot.show()

        [i1, i3, i2a, i2b] = P5().apply(graph, [i])

        if visualize_tests:
            pyplot.title("Correct subgraph output", fontsize=16)
            visualize_graph_3d(graph)
            pyplot.show()

            pyplot.title("Correct subgraph output (layer=1)", fontsize=16)
            visualize_graph_layer(graph, 1)
            pyplot.show()

            pyplot.title("Correct subgraph output (layer=2)", fontsize=16)
            visualize_graph_layer(graph, 2)
            pyplot.show()

        # if edges are unchanged
        self.assertTrue(graph.has_edge(e0a, e1))
        self.assertTrue(graph.has_edge(e1, e12))
        self.assertTrue(graph.has_edge(e12, e0a))
        self.assertTrue(graph.has_edge(e0a, e2))
        self.assertTrue(graph.has_edge(e2, e12))
        self.assertTrue(graph.has_edge(e0a, e0b))
        self.assertTrue(graph.has_edge(e0b, e2))
        self.assertTrue(graph.has_edge(e2, e23))
        self.assertTrue(graph.has_edge(e23, e0b))
        self.assertTrue(graph.has_edge(e0b, e3))
        self.assertTrue(graph.has_edge(e3, e23))
        self.assertTrue(graph.has_edge(e0b, e0c))
        self.assertTrue(graph.has_edge(e0c, e3))
        self.assertTrue(graph.has_edge(e3, e31))
        self.assertTrue(graph.has_edge(e31, e0c))
        self.assertTrue(graph.has_edge(e0c, e1))
        self.assertTrue(graph.has_edge(e1, e31))

        # if interior links are unchanged
        self.assertTrue(graph.has_edge(i, e1))
        self.assertTrue(graph.has_edge(i, e2))
        self.assertTrue(graph.has_edge(i, e3))
        self.assertTrue(graph.has_edge(i_0a_1_12, e0a))
        self.assertTrue(graph.has_edge(i_0a_1_12, e1))
        self.assertTrue(graph.has_edge(i_0a_1_12, e12))
        self.assertTrue(graph.has_edge(i_0a_12_2, e0a))
        self.assertTrue(graph.has_edge(i_0a_12_2, e12))
        self.assertTrue(graph.has_edge(i_0a_12_2, e2))
        self.assertTrue(graph.has_edge(i_0a_0b_2, e0a))
        self.assertTrue(graph.has_edge(i_0a_0b_2, e0b))
        self.assertTrue(graph.has_edge(i_0a_0b_2, e2))
        self.assertTrue(graph.has_edge(i_0b_2_23, e0b))
        self.assertTrue(graph.has_edge(i_0b_2_23, e2))
        self.assertTrue(graph.has_edge(i_0b_2_23, e23))
        self.assertTrue(graph.has_edge(i_0b_23_3, e0b))
        self.assertTrue(graph.has_edge(i_0b_23_3, e23))
        self.assertTrue(graph.has_edge(i_0b_23_3, e3))
        self.assertTrue(graph.has_edge(i_0b_0c_3, e0b))
        self.assertTrue(graph.has_edge(i_0b_0c_3, e3))
        self.assertTrue(graph.has_edge(i_0b_0c_3, e0c))
        self.assertTrue(graph.has_edge(i_0c_1_31, e1))
        self.assertTrue(graph.has_edge(i_0c_1_31, e31))
        self.assertTrue(graph.has_edge(i_0c_1_31, e0c))
        self.assertTrue(graph.has_edge(i_0c_3_31, e31))
        self.assertTrue(graph.has_edge(i_0c_3_31, e3))
        self.assertTrue(graph.has_edge(i_0c_3_31, e0c))

        # if vertex labels are unchanged
        self.assertEqual(graph.nodes[e0a]['label'], 'E')
        self.assertEqual(graph.nodes[e1]['label'], 'E')
        self.assertEqual(graph.nodes[e0b]['label'], 'E')
        self.assertEqual(graph.nodes[e0c]['label'], 'E')
        self.assertEqual(graph.nodes[e2]['label'], 'E')
        self.assertEqual(graph.nodes[e12]['label'], 'E')
        self.assertEqual(graph.nodes[e3]['label'], 'E')
        self.assertEqual(graph.nodes[e23]['label'], 'E')
        self.assertEqual(graph.nodes[e31]['label'], 'E')

        # if number of neighbors is unchanged
        # if each vertex has correct number of neighbors (based on neighbour interiors count)
        for n in [e0a, e1, e0b, e0c, e2, e12, e3, e23, e31]:
            node_neighbors = get_neighbors_at(graph, n,
                                              graph.nodes[n]['layer'])
            i_neighbors = [
                x for x in node_neighbors if graph.nodes[x]['label'] == 'I'
                or graph.nodes[x]['label'] == 'i'
            ]
            e_neighbors = [
                x for x in node_neighbors if graph.nodes[x]['label'] == 'E'
                or graph.nodes[x]['label'] == 'e'
            ]
            if len(e_neighbors) == len(i_neighbors):
                self.assertEqual(len(node_neighbors), len(i_neighbors) * 2)
            else:
                self.assertEqual(len(node_neighbors),
                                 (len(i_neighbors) * 2) + 1)

        # if vertices position is unchanged
        self.assertEqual(graph.nodes[e0a]['position'], (1.0, 1.0))
        self.assertEqual(graph.nodes[e1]['position'], (1.0, 9.0))
        self.assertEqual(graph.nodes[e0b]['position'], (9.0, 1.0))
        self.assertEqual(graph.nodes[e0c]['position'], (9.0, 9.0))
        self.assertEqual(graph.nodes[e2]['position'], (5.0, 5.0))
        self.assertEqual(graph.nodes[e12]['position'], (3.0, 7.0))
        self.assertEqual(graph.nodes[e3]['position'], (7.0, 7.0))
        self.assertEqual(graph.nodes[e23]['position'], (6.0, 6.0))
        self.assertEqual(graph.nodes[e31]['position'], (4.0, 8.0))
Exemple #21
0
    def test_in_bigger_graph(self):
        graph = Graph()
        positions = [(0, 0), (0, 1), (1, 0), (0, 0.5), (0.5, 0.5)]

        vx_e1 = gen_name()
        vx_e2 = gen_name()
        vx_e3 = gen_name()
        vx_e12 = gen_name()
        vx_e23 = gen_name()
        graph.add_node(vx_e1, layer=0, position=positions[0], label='E')
        graph.add_node(vx_e2, layer=0, position=positions[1], label='E')
        graph.add_node(vx_e3, layer=0, position=positions[2], label='E')
        graph.add_node(vx_e12, layer=0, position=positions[3], label='E')
        graph.add_node(vx_e23, layer=0, position=positions[4], label='E')

        graph.add_edge(vx_e1, vx_e12)
        graph.add_edge(vx_e12, vx_e2)
        graph.add_edge(vx_e2, vx_e23)
        graph.add_edge(vx_e23, vx_e3)
        graph.add_edge(vx_e3, vx_e1)

        vx_e1122 = gen_name()
        graph.add_node(vx_e1122, layer=0, position=(-0.5, 0.5), label='E')
        graph.add_edge(vx_e1, vx_e1122)
        graph.add_edge(vx_e12, vx_e1122)
        graph.add_edge(vx_e2, vx_e1122)

        vx_e2233 = gen_name()
        graph.add_node(vx_e2233, layer=0, position=(1, 1), label='E')
        graph.add_edge(vx_e2, vx_e2233)
        graph.add_edge(vx_e23, vx_e2233)
        graph.add_edge(vx_e3, vx_e2233)

        vx_e13 = gen_name()
        graph.add_node(vx_e13, layer=0, position=(0.5, -0.5), label='E')
        graph.add_edge(vx_e1, vx_e13)
        graph.add_edge(vx_e3, vx_e13)

        I = add_interior(graph, vx_e1, vx_e2, vx_e3)
        I1 = add_interior(graph, vx_e1122, vx_e1, vx_e12)
        I2 = add_interior(graph, vx_e1122, vx_e12, vx_e2)
        I3 = add_interior(graph, vx_e2233, vx_e2, vx_e23)
        I4 = add_interior(graph, vx_e2233, vx_e23, vx_e3)
        I5 = add_interior(graph, vx_e1, vx_e3, vx_e13)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        [i1, i2, i3] = P4().apply(graph, [I])

        self.assertEqual(len(graph.nodes()), 22)
        self.assertEqual(len(graph.edges()), 50)

        self.assertEqual(graph.nodes[I]['label'], 'i')
        self.assertTrue(graph.has_edge(I, i1))
        self.assertTrue(graph.has_edge(I, i2))
        self.assertTrue(graph.has_edge(I, i3))

        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i2]['label'], 'I')
        self.assertEqual(graph.nodes[i3]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[I]['layer'] + 1)
        self.assertEqual(graph.nodes[i2]['layer'], graph.nodes[I]['layer'] + 1)
        self.assertEqual(graph.nodes[i3]['layer'], graph.nodes[I]['layer'] + 1)

        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i2_neighbors = get_neighbors_at(graph, i2, graph.nodes[i2]['layer'])
        self.assertEqual(len(i2_neighbors), 3)
        i3_neighbors = get_neighbors_at(graph, i3, graph.nodes[i3]['layer'])
        self.assertEqual(len(i3_neighbors), 3)

        i1_i2_n = [x for x in i1_neighbors if x in i2_neighbors]
        i1_i3_n = [x for x in i1_neighbors if x in i3_neighbors]
        i2_i3_n = [x for x in i2_neighbors if x in i3_neighbors]

        # Test i1-only neighbors
        for n in [
                x for x in i1_neighbors
                if x not in i1_i2_n and x not in i1_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test i2-only neighbors
        for n in [
                x for x in i2_neighbors
                if x not in i1_i2_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i2]['layer'])))

        # Test i3-only neighbors
        for n in [
                x for x in i3_neighbors
                if x not in i1_i3_n and x not in i2_i3_n
        ]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                3, len(get_neighbors_at(graph, n, graph.nodes[i3]['layer'])))

        # Test nodes connected to 2 interiors
        for n in [x for x in i1_i2_n if x not in i1_i3_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i1_i3_n if x not in i1_i2_n and x not in i2_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        for n in [x for x in i2_i3_n if x not in i1_i2_n and x not in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                5, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        # Test nodes connected to 3 interiors
        for n in [x for x in i2_i3_n if x in i1_i2_n and x in i1_i3_n]:
            self.assertEqual(graph.nodes[n]['label'], 'E')
            self.assertEqual(
                7, len(get_neighbors_at(graph, n, graph.nodes[i1]['layer'])))

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()
Exemple #22
0
    def __check_prod_input(graph: Graph, prod_input: List[str]):

        # Check number of vertices delivered
        if len(set(prod_input)) != 6:
            raise ValueError('Too few interiors in prod_input (6 required)')

        # Check layers
        up_layer = graph.nodes()[prod_input[0]]['layer']
        down_layer = graph.nodes()[prod_input[2]]['layer']
        if any(graph.nodes()[interior]['layer'] != up_layer
               for interior in prod_input[:2]):
            raise ValueError('First two interior are not in the same layer')
        if any(graph.nodes()[interior]['layer'] != down_layer
               for interior in prod_input[2:]):
            raise ValueError('Four last interiors are not in the same layer')
        if up_layer + 1 != down_layer:
            raise ValueError('Upper layer is not right above lower one')

        # Check delivered vertices labels
        if any(graph.nodes()[interior]['label'] != 'i'
               for interior in prod_input[:2]):
            raise ValueError('First two interior don not have "i" label')
        if any(graph.nodes()[interior]['label'] != 'I'
               for interior in prod_input[2:]):
            raise ValueError('Four last interior don not have "I" label')

        # Check connections between delivered vertices
        neighbors_in_lower_layer = {prod_input[0]: set(), prod_input[1]: set()}
        for upper_interior in prod_input[:2]:
            for bottom_neighbor in get_neighbors_at(graph, upper_interior,
                                                    down_layer):
                neighbors_in_lower_layer[upper_interior].add(bottom_neighbor)
        for lower_interior in prod_input[2:]:
            if lower_interior not in neighbors_in_lower_layer[prod_input[0]]\
              and lower_interior not in neighbors_in_lower_layer[prod_input[1]]:
                raise ValueError(
                    'Upper interiors not connected properly to lower ones')
        if len(neighbors_in_lower_layer[prod_input[0]]) != 2:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')
        if len(neighbors_in_lower_layer[prod_input[1]]) != 2:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')

        # maps lower interiors to its parent in upper layer
        lower_to_upper = dict()
        for upper in neighbors_in_lower_layer:
            for lower in neighbors_in_lower_layer[upper]:
                lower_to_upper[lower] = upper

        # Check common neighbors of upper interiors
        upper_neighbors = get_common_neighbors(graph, prod_input[0],
                                               prod_input[1], up_layer)
        if len(upper_neighbors) != 2:
            raise ValueError('Upper interiors don not have 2 common neighbors')

        # Get those neighbors and their positions as well as center position between them
        v1_up, v2_up = upper_neighbors
        pos_v1 = graph.nodes()[v1_up]['position']
        pos_v2 = graph.nodes()[v2_up]['position']
        x = (pos_v1[0] + pos_v2[0]) / 2
        y = (pos_v1[1] + pos_v2[1]) / 2
        pos_center = (x, y)

        # Check if they are connected
        if not graph.has_edge(v1_up, v2_up):
            raise ValueError('Upper vertices are not connected')

        # Prepare list of vertices in lower layer
        pairs_of_lower = [set(), set(), set()]
        for interior in prod_input[2:]:
            for v in get_neighbors_at(graph, interior, down_layer):
                if graph.nodes()[v]['position'] == pos_v1:
                    pairs_of_lower[0].add((v, lower_to_upper[interior]))
                elif graph.nodes()[v]['position'] == pos_v2:
                    pairs_of_lower[1].add((v, lower_to_upper[interior]))
                elif graph.nodes()[v]['position'] == pos_center:
                    if v not in pairs_of_lower[2]:
                        pairs_of_lower[2].add((v, lower_to_upper[interior]))

        # Check if pair is indeed pair of vertices
        for pair in pairs_of_lower:
            s = set(map(lambda x: x[0], pair))
            if len(s) != 2:
                raise ValueError(
                    'Connections between lower vertices are incorrect')

        # separate vertices based on side it is on (vertices on one side are connected)
        vertices_by_side = {prod_input[0]: list(), prod_input[1]: list()}
        for pair in pairs_of_lower:
            for v in pair:
                vertices_by_side[v[1]].append(v[0])
        # Now vertices_by_side should be dict where keys are id's of interiors in upper layer
        # and values are lists of vertices in loser layer on belonging to this parent
        # also last element on this list is center between two previous

        # Check if vertices on one side are properly connected
        for side in vertices_by_side:
            v1, v2, v3 = vertices_by_side[side]
            if not graph.has_edge(v1, v3):
                raise ValueError(
                    'Connections between lower vertices are incorrect')
            if not graph.has_edge(v2, v3):
                raise ValueError(
                    'Connections between lower vertices are incorrect')

        # Check if middle vertices are properly connected to two interiors each
        for side in vertices_by_side:
            v1, v2, v3 = vertices_by_side[side]  # v3 is vertex in the middle
            lower_interiors = get_neighbors_at(graph, side, down_layer)
            for interior in lower_interiors:
                if interior not in graph.neighbors(v3):
                    raise ValueError(
                        'Connections between lower vertices are incorrect')

        # Check if vertices on opposite sides are connected
        # (they obviously shouldn't be right?)
        for v in vertices_by_side[prod_input[0]]:
            if any(
                    graph.has_edge(v, v_other)
                    for v_other in vertices_by_side[prod_input[1]]):
                raise ValueError(
                    'Connections between lower vertices are incorrect')

        # Check if labels are E
        all_vertices = vertices_by_side[prod_input[0]] + vertices_by_side[
            prod_input[1]] + [v1_up, v2_up]
        if any(graph.nodes()[v]['label'] != 'E' for v in all_vertices):
            raise ValueError('Not all vertices have label E')
Exemple #23
0
    def apply(self,
              graph: Graph,
              prod_input: List[str],
              orientation: int = 0,
              **kwargs) -> List[str]:
        self.__check_prod_input(graph, prod_input)

        layer = graph.nodes()[prod_input[0]]['layer']
        overlapping_vertices = find_overlapping_vertices(graph)
        vertices_to_join = set()
        for overlapping_vertice1, overlapping_vertice2 in overlapping_vertices:
            vertices_to_join.add(overlapping_vertice1)
            vertices_to_join.add(overlapping_vertice2)

        vertices_to_join_group1 = [
            vertice for vertice in vertices_to_join
            if graph.nodes()[vertice]['position'] == graph.nodes()[list(
                vertices_to_join)[0]]['position']
        ]
        vertices_to_join_group2 = [
            vertice for vertice in vertices_to_join
            if vertice not in vertices_to_join_group1
        ]

        vertice1_group1_neighbours = get_neighbors_at(
            graph, vertices_to_join_group1[0], layer)
        vertice2_group1_neighbours = get_neighbors_at(
            graph, vertices_to_join_group1[1], layer)
        vertice1_group2_neighbours = get_neighbors_at(
            graph, vertices_to_join_group2[0], layer)
        vertice2_group2_neighbours = get_neighbors_at(
            graph, vertices_to_join_group2[1], layer)

        vertice1_group1_I_neighbours = [
            neighbour for neighbour in vertice1_group1_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        vertice2_group1_I_neighbours = [
            neighbour for neighbour in vertice2_group1_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        vertice1_group2_I_neighbours = [
            neighbour for neighbour in vertice1_group2_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        vertice2_group2_I_neighbours = [
            neighbour for neighbour in vertice2_group2_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]

        common_I_neighbour_vertices_to_join = []
        if vertice1_group1_I_neighbours == vertice1_group2_I_neighbours:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[0])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[0])
        elif vertice1_group1_I_neighbours == vertice2_group2_I_neighbours:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[0])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[1])
        elif vertice2_group1_I_neighbours == vertice1_group2_I_neighbours:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[1])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[0])
        elif vertice2_group1_I_neighbours == vertice2_group2_I_neighbours:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[1])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[1])

        if graph.has_edge(common_I_neighbour_vertices_to_join[0],
                          common_I_neighbour_vertices_to_join[1]):
            graph.remove_edge(common_I_neighbour_vertices_to_join[0],
                              common_I_neighbour_vertices_to_join[1])

        join_overlapping_vertices(graph, vertices_to_join_group1[0],
                                  vertices_to_join_group1[1], layer)
        join_overlapping_vertices(graph, vertices_to_join_group2[0],
                                  vertices_to_join_group2[1], layer)

        return prod_input
Exemple #24
0
    def __check_prod_input(graph: Graph, prod_input: List[str]):

        # Check number of vertices delivered
        if len(prod_input) != 6:
            raise ValueError(
                'Wrong number of interiors in prod_input (6 required)')

        nodes = [(node_id, graph.nodes()[node_id]) for node_id in prod_input]
        up_layer_nodes = [
            node_id for node_id, data in nodes if data['label'] == 'i'
        ]
        down_layer_nodes = [
            node_id for node_id, data in nodes if data['label'] == 'I'
        ]
        if len(up_layer_nodes) != 2:
            raise ValueError(
                'Wrong number of interiors in first layer (2 required)')
        if len(down_layer_nodes) != 4:
            raise ValueError(
                'Wrong number of interiors in second layer (4 required)')

        # Check layers
        up_layer = graph.nodes()[up_layer_nodes[0]]['layer']
        down_layer = graph.nodes()[down_layer_nodes[0]]['layer']
        if any(graph.nodes()[node]['layer'] != up_layer
               for node in up_layer_nodes):
            raise ValueError('"i" interiors are not in the same layer')
        if any(graph.nodes()[node]['layer'] != down_layer
               for node in down_layer_nodes):
            raise ValueError('"I" interiors are not in the same layer')
        if up_layer + 1 != down_layer:
            raise ValueError('Upper layer is not right above lower one')

        # Check connections between delivered vertices
        interior_neighbours0 = [
            node_id for node_id in graph.neighbors(up_layer_nodes[0])
            if graph.nodes()[node_id]['label'] == 'I'
        ]
        interior_neighbours1 = [
            node_id for node_id in graph.neighbors(up_layer_nodes[1])
            if graph.nodes()[node_id]['label'] == 'I'
        ]
        if len(interior_neighbours0) != len(interior_neighbours1) != 2:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')
        if len(common_elements(interior_neighbours0,
                               interior_neighbours1)) != 0:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')
        if len(common_elements(interior_neighbours0, down_layer_nodes)) != 2:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')
        if len(common_elements(interior_neighbours1, down_layer_nodes)) != 2:
            raise ValueError(
                'Upper interiors not connected properly to lower ones')

        # Check correctness of the graph connections

        def check_structure(interior_nodes, layer_num):
            for interior_node in interior_nodes:
                neighbours = get_neighbors_at(graph, interior_node, layer_num)
                if len(neighbours) > 3:
                    raise ValueError(
                        'Wrong number of neighbours of an interior vertex')
                for n in neighbours:
                    if graph.nodes()[n]['label'] != "E":
                        raise ValueError('Vertex does not have "E" label')

            common_neighbors = get_common_neighbors(graph, interior_nodes[0],
                                                    interior_nodes[1],
                                                    layer_num)
            if len(common_neighbors) > 2:
                raise ValueError('Interiors have more than 2 common neighbors')

            return common_neighbors

        # Check correctness of upper layer
        up_e = check_structure(up_layer_nodes, up_layer)
        # Check correctness of lower layer
        check_structure(interior_neighbours0, down_layer)
        check_structure(interior_neighbours1, down_layer)

        if len(up_e) != 2:
            raise ValueError(
                'Upper kayer interiors have less than 2 common neighbors')
        if not are_connected(graph, up_e):
            raise ValueError('E vertices in upper layer not connected')

        # check nodes with the same position
        n1 = sorted(
            set(
                get_neighbors_at(graph, interior_neighbours0[0], down_layer) +
                get_neighbors_at(graph, interior_neighbours0[1], down_layer)))

        n2 = sorted(
            set(
                get_neighbors_at(graph, interior_neighbours1[0], down_layer) +
                get_neighbors_at(graph, interior_neighbours1[1], down_layer)))
        c = common_elements(n1, n2)
        if len(c) != 1:
            raise ValueError(
                'There is not exactly 1 common vertex on the line')
        nn = [
            x for x in graph.neighbors(c[0])
            if graph.nodes()[x]['label'] == 'I'
        ]
        if len(common_elements(nn, prod_input)) != 2:
            raise ValueError(
                'Wrong number of interior neighbours of the common vertex')

        n1.remove(c[0])
        n2.remove(c[0])

        n1_pos = [graph.nodes()[n]['position'] for n in n1]
        n2_pos = [graph.nodes()[n]['position'] for n in n2]
        n1 = [
            n for n in n1 for pos in n2_pos
            if graph.nodes()[n]['position'] == pos
        ]
        n2 = [
            n for n in n2 for pos in n1_pos
            if graph.nodes()[n]['position'] == pos
        ]
        if len(n1) != 2:
            raise ValueError(
                'There are not exactly 2 vertices with the same position')
        if len(n2) != 2:
            raise ValueError(
                'There are not exactly 2 vertices with the same position')
        if not are_connected(graph, n1):
            raise ValueError('Vertices on the line not connected')
        if not are_connected(graph, n2):
            raise ValueError('Vertices on the line not connected')
        a1 = [
            v for v in n1 if len(
                common_elements([
                    x for x in graph.neighbors(v)
                    if graph.nodes()[x]['label'] == 'I'
                ], prod_input)) == 2
        ]
        a2 = [
            v for v in n2 if len(
                common_elements([
                    x for x in graph.neighbors(v)
                    if graph.nodes()[x]['label'] == 'I'
                ], prod_input)) == 2
        ]
        if len(a1) != 1:
            raise ValueError(
                'Wrong interior connections for vertices on the line')
        if len(a2) != 1:
            raise ValueError(
                'Wrong interior connections for vertices on the line')
        if not are_connected(graph, [a1[0], c[0]]):
            raise ValueError('Vertices on the line not connected')
        if not are_connected(graph, [a2[0], c[0]]):
            raise ValueError('Vertices on the line not connected')
        return down_layer, zip(n1, n2)
    def test_happy_path(self):
        graph = Graph()
        positions = [(1.0, 1.0), (1.0, 2.0), (1.0, 3.0), (2.0, 3.0),
                     (3.0, 3.0), (2.0, 2.0)]

        [e1, e12, e2, e23, e3,
         e31] = self.create_nodes(graph, 1, 'E', positions)
        self.create_edges_chain(graph, [e1, e12, e2, e23, e3, e31, e1])

        i = add_interior(graph, e1, e2, e3)

        if visualize_tests:
            pyplot.title("Correct input", fontsize=16)
            visualize_graph_3d(graph)
            pyplot.show()

        [i1, i3, i2a, i2b] = P5().apply(graph, [i])

        if visualize_tests:
            pyplot.title("Correct output", fontsize=16)
            visualize_graph_3d(graph)
            pyplot.show()

            pyplot.title("Correct output (layer = 1)", fontsize=16)
            visualize_graph_layer(graph, 1)
            pyplot.show()

            pyplot.title("Correct output (layer = 2)", fontsize=16)
            visualize_graph_layer(graph, 2)
            pyplot.show()

        # if correct number of nodes and edges
        self.assertEqual(len(graph.nodes()), 17)
        self.assertEqual(len(graph.edges()), 34)

        # if cross-layer interior connections
        self.assertEqual(graph.nodes[i]['label'], 'i')
        self.assertTrue(graph.has_edge(i, i1))
        self.assertTrue(graph.has_edge(i, i3))
        self.assertTrue(graph.has_edge(i, i2a))
        self.assertTrue(graph.has_edge(i, i2b))

        # if new interiors has correct labels and layers
        self.assertEqual(graph.nodes[i1]['label'], 'I')
        self.assertEqual(graph.nodes[i3]['label'], 'I')
        self.assertEqual(graph.nodes[i2a]['label'], 'I')
        self.assertEqual(graph.nodes[i2b]['label'], 'I')
        self.assertEqual(graph.nodes[i1]['layer'], graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i3]['layer'], graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i2a]['layer'],
                         graph.nodes[i]['layer'] + 1)
        self.assertEqual(graph.nodes[i2b]['layer'],
                         graph.nodes[i]['layer'] + 1)

        # if each new interior has 3 neighbors
        i1_neighbors = get_neighbors_at(graph, i1, graph.nodes[i1]['layer'])
        self.assertEqual(len(i1_neighbors), 3)
        i3_neighbors = get_neighbors_at(graph, i3, graph.nodes[i3]['layer'])
        self.assertEqual(len(i3_neighbors), 3)
        i2a_neighbors = get_neighbors_at(graph, i2a, graph.nodes[i2a]['layer'])
        self.assertEqual(len(i2a_neighbors), 3)
        i2b_neighbors = get_neighbors_at(graph, i2b, graph.nodes[i2b]['layer'])
        self.assertEqual(len(i2b_neighbors), 3)

        # if new nodes are in correct positions
        new_e1 = get_node_at(graph, 2, (1.0, 1.0))
        new_e12 = get_node_at(graph, 2, (1.0, 2.0))
        new_e2 = get_node_at(graph, 2, (1.0, 3.0))
        new_e23 = get_node_at(graph, 2, (2.0, 3.0))
        new_e3 = get_node_at(graph, 2, (3.0, 3.0))
        new_e31 = get_node_at(graph, 2, (2.0, 2.0))
        self.assertIsNotNone(new_e1)
        self.assertIsNotNone(new_e12)
        self.assertIsNotNone(new_e2)
        self.assertIsNotNone(new_e23)
        self.assertIsNotNone(new_e3)
        self.assertIsNotNone(new_e31)

        # if interiors connect with all new 6 vertices
        all_neighbors = i1_neighbors + i3_neighbors + i2a_neighbors + i2b_neighbors
        all_neighbors = list(dict.fromkeys(all_neighbors))  # remove duplicates
        self.assertEqual(len(all_neighbors), 6)

        # if each vertex has correct label
        for n in all_neighbors:
            self.assertEqual(graph.nodes[n]['label'], 'E')

        # if each vertex has correct number of neighbors (based on neighbour interiors count)
        for n in all_neighbors:
            node_neighbors = get_neighbors_at(graph, n,
                                              graph.nodes[n]['layer'])
            i_neighbors = [
                x for x in node_neighbors if graph.nodes[x]['label'] == 'I'
            ]
            if len(i_neighbors) == 1:
                self.assertEqual(len(node_neighbors), 3)
            elif len(i_neighbors) == 2:
                self.assertEqual(len(node_neighbors), 5)
            else:  # 4
                self.assertEqual(len(node_neighbors), 9)
Exemple #26
0
    def __check_prod_input(graph, prod_input):

        if len(set(prod_input)) != 3:
            raise ValueError('too few interiors')
        layer = graph.nodes()[prod_input[0]]['layer']
        if any(graph.nodes()[interior]['layer'] != layer
               for interior in prod_input[1:]):
            raise ValueError('interior vertices come from different layers')
        if any(graph.nodes()[interior]['label'] != 'I'
               for interior in prod_input):
            raise ValueError('interior vertices must have I label')

        all_I_neighbours = []

        for interior in prod_input:
            interior_neighbours = get_neighbors_at(graph, interior, layer)
            if len(interior_neighbours) not in [2, 3]:
                raise ValueError('wrongly connected interior vertices')

            for neighbour in interior_neighbours:
                if graph.nodes()[neighbour]['label'] != 'E':
                    raise ValueError(
                        'interior vertices can be connect only with E vertices'
                    )

                all_I_neighbours.append(neighbour)

        E_vertices = get_vertices_from_layer(graph, layer, "E")
        E_vertices_position_prev_layer = []
        if any(E_vertice not in all_I_neighbours for E_vertice in E_vertices):
            raise ValueError('wrongly connected E vertices')
        for E_vertice in E_vertices:
            E_vertice_neighbours = get_neighbors_at(graph, E_vertice, layer)
            if len([
                    I_node for I_node in E_vertice_neighbours
                    if graph.nodes()[I_node]['label'] == "I"
            ]) not in [1, 2]:
                raise ValueError(
                    'each E vertice must be connected with I vertice')
            E_vertice_E_neighbours = [
                neighbour for neighbour in E_vertice_neighbours
                if graph.nodes()[neighbour]['label'] == "E"
            ]
            if len(E_vertice_E_neighbours) not in [1, 2, 3]:
                raise ValueError(
                    'each E vertice must be connected with at least one E vertice'
                )
            corresponding_vertice = get_node_at(
                graph, layer - 1,
                graph.nodes()[E_vertice]['position'])
            if corresponding_vertice is not None:
                E_vertices_position_prev_layer.append(corresponding_vertice)

        if len(E_vertices_position_prev_layer) != 4 and len(
                E_vertices_position_prev_layer) != 6:
            raise ValueError(
                'positions of corresponding vertices between layers are incorrect'
            )
        corresponding_positions = [
            graph.nodes()[E_vertice]['position']
            for E_vertice in E_vertices_position_prev_layer
        ]
        noncorresponding_E_vertices = [
            E_vertice for E_vertice in E_vertices if graph.nodes()[E_vertice]
            ['position'] not in corresponding_positions
        ]
        possible_positions = []
        for i in range(len(corresponding_positions) - 1):
            x1, y1 = corresponding_positions[i]
            for j in range(i + 1, len(corresponding_positions)):
                x2, y2 = corresponding_positions[j]
                possible_positions.append(((x1 + x2) / 2, (y1 + y2) / 2))
        for E_vertice in noncorresponding_E_vertices:
            x, y = graph.nodes()[E_vertice]['position']
            if (x, y) not in possible_positions:
                raise ValueError(
                    'position of noncorresponding vertice is incorrect')

        overlapping_vertices = find_overlapping_vertices(graph)

        if len(overlapping_vertices) != 4 or \
                any(overlapping_vertice1 not in set(all_I_neighbours)
                    or overlapping_vertice2 not in set(all_I_neighbours)
                    for overlapping_vertice1, overlapping_vertice2 in overlapping_vertices):
            raise ValueError('incorrect shape of graph')

        vertices_to_join = set()
        for overlapping_vertice1, overlapping_vertice2 in overlapping_vertices:
            vertices_to_join.add(overlapping_vertice1)
            vertices_to_join.add(overlapping_vertice2)

        if len(vertices_to_join) != 4:
            raise ValueError('too many overlapping vertices')

        vertices_to_join_group1 = [
            vertice for vertice in vertices_to_join
            if graph.nodes()[vertice]['position'] == graph.nodes()[list(
                vertices_to_join)[0]]['position']
        ]
        vertices_to_join_group2 = [
            vertice for vertice in vertices_to_join
            if vertice not in vertices_to_join_group1
        ]

        if len(vertices_to_join_group1) != 2 or len(
                vertices_to_join_group2) != 2:
            raise ValueError('too many overlapping vertices')

        vertice1_neighbours = get_neighbors_at(graph,
                                               vertices_to_join_group1[0],
                                               layer)
        vertice2_neighbours = get_neighbors_at(graph,
                                               vertices_to_join_group1[1],
                                               layer)
        vertice3_neighbours = get_neighbors_at(graph,
                                               vertices_to_join_group2[0],
                                               layer)
        vertice4_neighbours = get_neighbors_at(graph,
                                               vertices_to_join_group2[1],
                                               layer)

        I_neighbours_vertice1 = [
            neighbour for neighbour in vertice1_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        I_neighbours_vertice2 = [
            neighbour for neighbour in vertice2_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        I_neighbours_vertice3 = [
            neighbour for neighbour in vertice3_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        I_neighbours_vertice4 = [
            neighbour for neighbour in vertice4_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]

        if len(I_neighbours_vertice1) != 1 or len(I_neighbours_vertice2) != 1 or \
            len(I_neighbours_vertice3) != 1 or len(I_neighbours_vertice4) != 1:
            raise ValueError(
                'vertices to join wrongly connected with I vertices')

        common_I_neighbour_vertices_to_join = []
        if I_neighbours_vertice1 == I_neighbours_vertice3:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[0])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[0])
        elif I_neighbours_vertice1 == I_neighbours_vertice4:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[0])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[1])
        elif I_neighbours_vertice2 == I_neighbours_vertice3:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[1])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[0])
        elif I_neighbours_vertice2 == I_neighbours_vertice4:
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group1[1])
            common_I_neighbour_vertices_to_join.append(
                vertices_to_join_group2[1])
        else:
            raise ValueError(
                'vertices to join wrongly connected with I vertices')

        noncommon_I_neighbour_vertices_to_join = [
            vertice for vertice in vertices_to_join
            if vertice not in common_I_neighbour_vertices_to_join
        ]
        if len(noncommon_I_neighbour_vertices_to_join) != 2:
            raise ValueError(
                'vertices to join wrongly connected with I vertices')
        if len(
                set(common_I_neighbour_vertices_to_join).intersection(
                    set(noncommon_I_neighbour_vertices_to_join))) != 0:
            raise ValueError('vertices to join wrongly connected')

        common_vertice1_neighbours = get_neighbors_at(
            graph, common_I_neighbour_vertices_to_join[0], layer)
        common_vertice2_neighbours = get_neighbors_at(
            graph, common_I_neighbour_vertices_to_join[1], layer)

        if common_I_neighbour_vertices_to_join[
                1] not in common_vertice1_neighbours:
            raise ValueError(
                'vertices to join with common I neighbour are not connected')
        if len(
                set(common_vertice1_neighbours).intersection(
                    set(common_vertice2_neighbours))) not in [1, 2]:
            raise ValueError(
                'vertices to join with common I neighbour are wrongly connected'
            )

        noncommon_vertice1_neighbours = get_neighbors_at(
            graph, noncommon_I_neighbour_vertices_to_join[0], layer)
        noncommon_vertice2_neighbours = get_neighbors_at(
            graph, noncommon_I_neighbour_vertices_to_join[1], layer)

        if noncommon_I_neighbour_vertices_to_join[
                1] in noncommon_vertice1_neighbours:
            raise ValueError(
                'vertices to join with non-common I neighbour are connected')
        if len(
                set(noncommon_vertice1_neighbours).intersection(
                    set(noncommon_vertice2_neighbours))) not in [1, 2]:
            raise ValueError(
                'vertices to join with common I neighbour are wrongly connected'
            )
Exemple #27
0
    def __check_prod_input(graph, prod_input):

        if len(set(prod_input)) != 4:
            raise ValueError('too few interiors')
        layer = graph.nodes()[prod_input[0]]['layer']
        if any(graph.nodes()[interior]['layer'] != layer
               for interior in prod_input[1:]):
            raise ValueError('interior vertices come from different layers')
        if any(graph.nodes()[interior]['label'] != 'I'
               for interior in prod_input):
            raise ValueError('interior vertices must have I label')

        all_I_neighbours = []

        for interior in prod_input:
            interior_neighbours = get_neighbors_at(graph, interior, layer)
            if len(interior_neighbours) not in [2, 3]:
                raise ValueError('wrongly connected interior vertices')

            for neighbour in interior_neighbours:
                if graph.nodes()[neighbour]['label'] != 'E':
                    raise ValueError(
                        'interior vertices can be connect only with E vertices'
                    )

                all_I_neighbours.append(neighbour)

        E_vertices = get_vertices_from_layer(graph, layer, 'E')
        E_vertices_position_prev_layer = []
        if any(E_vertice not in all_I_neighbours for E_vertice in E_vertices):
            raise ValueError('wrongly connected E vertices')
        for E_vertice in E_vertices:
            E_vertice_neighbours = get_neighbors_at(graph, E_vertice, layer)
            if len([
                    I_node for I_node in E_vertice_neighbours
                    if graph.nodes()[I_node]['label'] == "I"
            ]) != 2:
                raise ValueError(
                    'each E vertice must be connected with two I vertices')
            E_vertice_E_neighbours = [
                neighbour for neighbour in E_vertice_neighbours
                if graph.nodes()[neighbour]['label'] == "E"
            ]
            if len(E_vertice_E_neighbours) not in [1, 2, 3, 4]:
                print(len(E_vertice_E_neighbours))
                raise ValueError(
                    'each E vertice must be connected with at least one E vertice'
                )
            corresponding_vertice = get_node_at(
                graph, layer - 1,
                graph.nodes()[E_vertice]['position'])
            if corresponding_vertice is not None:
                E_vertices_position_prev_layer.append(corresponding_vertice)

        if len(E_vertices_position_prev_layer) != 2 and len(
                E_vertices_position_prev_layer) != 4:
            raise ValueError(
                'positions of corresponding vertices between layers are incorrect'
            )
        corresponding_positions = [
            graph.nodes()[E_vertice]['position']
            for E_vertice in E_vertices_position_prev_layer
        ]
        noncorresponding_E_vertices = [
            E_vertice for E_vertice in E_vertices if graph.nodes()[E_vertice]
            ['position'] not in corresponding_positions
        ]
        possible_positions = []
        for i in range(len(corresponding_positions) - 1):
            x1, y1 = corresponding_positions[i]
            for j in range(i + 1, len(corresponding_positions)):
                x2, y2 = corresponding_positions[j]
                possible_positions.append(((x1 + x2) / 2, (y1 + y2) / 2))
        for E_vertice in noncorresponding_E_vertices:
            x, y = graph.nodes()[E_vertice]['position']
            if (x, y) not in possible_positions:
                raise ValueError(
                    'positions of noncorresponding vertices are incorrect')

        overlapping_vertices = find_overlapping_vertices(graph)

        if len(overlapping_vertices) != 2 or \
                any(overlapping_vertice1 not in set(all_I_neighbours)
                    or overlapping_vertice2 not in set(all_I_neighbours)
                    for overlapping_vertice1, overlapping_vertice2 in overlapping_vertices):
            raise ValueError('incorrect shape of graph')

        vertices_to_join = [
            neighbour for neighbour in set(all_I_neighbours)
            if graph.nodes()[neighbour]['position'] == graph.nodes()[
                overlapping_vertices[0][0]]['position']
        ]

        if len(vertices_to_join) != 2:
            raise ValueError('too many overlapping vertices')

        vertice1_neighbours = get_neighbors_at(graph, vertices_to_join[0],
                                               layer)
        vertice2_neighbours = get_neighbors_at(graph, vertices_to_join[1],
                                               layer)

        common_neighbours = set(vertice1_neighbours).intersection(
            set(vertice2_neighbours))

        if len(common_neighbours) != 2:
            raise ValueError('vertices to join wrongly connected')

        I_neighbours_vertice1 = [
            neighbour for neighbour in vertice1_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]
        I_neighbours_vertice2 = [
            neighbour for neighbour in vertice2_neighbours
            if graph.nodes()[neighbour]['label'] == "I"
        ]

        if len(I_neighbours_vertice1) != 2 or len(I_neighbours_vertice2) != 2:
            raise ValueError(
                'vertices to join wrongly connected with I vertices')

        if len(set(I_neighbours_vertice1).intersection(
                I_neighbours_vertice2)) != 0:
            raise ValueError('vertices to join have common I neighbour')
Exemple #28
0
    def __check_prod_input(graph, prod_input):
        assert len(prod_input) == 4

        upper_layer = graph.nodes()[prod_input[0]]['layer']
        lower_layer = graph.nodes()[prod_input[2]]['layer']
        assert all(graph.nodes()[i]['layer'] == upper_layer
                   for i in prod_input[:2])
        assert all(graph.nodes()[i]['layer'] == lower_layer
                   for i in prod_input[2:])
        # upper layer means lower index
        assert upper_layer + 1 == lower_layer

        assert all(graph.nodes()[i]['label'] == 'i' for i in prod_input[:2])
        assert all(graph.nodes()[i]['label'] == 'I' for i in prod_input[2:])

        upper_i1, upper_i2 = prod_input[:2]
        upper_neighbors = get_common_neighbors(graph, upper_i1, upper_i2,
                                               upper_layer)
        assert len(upper_neighbors) == 2

        upper_v1, upper_v2 = upper_neighbors
        pos_upper_v1, pos_upper_v2 = [
            graph.nodes()[v]['position'] for v in upper_neighbors
        ]
        assert graph.has_edge(upper_v1, upper_v2)

        neighbors_in_lower_layer = {upper_i1: set(), upper_i2: set()}
        for upper_interior in upper_i1, upper_i2:
            for bottom_neighbor in get_neighbors_at(graph, upper_interior,
                                                    lower_layer):
                neighbors_in_lower_layer[upper_interior].add(bottom_neighbor)

        if prod_input[2] in neighbors_in_lower_layer[upper_i1]:
            assert prod_input[2] in neighbors_in_lower_layer[upper_i1] \
                   and prod_input[3] in neighbors_in_lower_layer[upper_i2]
            lower_i1, lower_i2 = prod_input[2:]
        else:
            assert prod_input[3] in neighbors_in_lower_layer[upper_i1] \
                   and prod_input[2] in neighbors_in_lower_layer[upper_i2]
            lower_i2, lower_i1 = prod_input[2:]

        lower_connected_neighbors = get_common_neighbors(
            graph, lower_i1, lower_i2, lower_layer)
        assert len(lower_connected_neighbors) == 1
        lower_connected_neighbor = lower_connected_neighbors[0]

        lower_i1_neighbors = get_neighbors_at(graph, lower_i1, lower_layer)
        lower_i1_neighbors.remove(lower_connected_neighbor)
        lower_i2_neighbors = get_neighbors_at(graph, lower_i2, lower_layer)
        lower_i2_neighbors.remove(lower_connected_neighbor)

        to_merge = [
            (v1, v2) for v1, v2 in itertools.product(lower_i1_neighbors,
                                                     lower_i2_neighbors)
            if graph.nodes()[v1]['position'] == graph.nodes()[v2]['position']
        ]
        assert len(to_merge) == 1
        to_merge = to_merge[0]
        pos_lower_connected_neighbor, pos_lower_to_merge = [
            graph.nodes()[v]['position']
            for v in [lower_connected_neighbor, to_merge[0]]
        ]

        if pos_lower_connected_neighbor == pos_upper_v1:
            assert pos_lower_connected_neighbor == pos_upper_v1 \
                   and pos_lower_to_merge == pos_upper_v2
        else:
            assert pos_lower_to_merge == pos_upper_v1 \
                   and pos_lower_connected_neighbor == pos_upper_v2

        all_vertices = upper_neighbors + lower_connected_neighbors + lower_i1_neighbors + lower_i2_neighbors
        for e in all_vertices:
            assert graph.nodes[e]['label'] == 'E'

        return to_merge
Exemple #29
0
    def test_happy_path(self):
        graph = Graph()

        e1_1, e2_1, e3_1, e4_1 = [gen_name() for _ in range(4)]
        graph.add_node(e1_1, layer=1, position=(0.0, 0.0), label='E')
        graph.add_node(e2_1, layer=1, position=(1.0, 0.0), label='E')
        graph.add_node(e3_1, layer=1, position=(0.5, 0.5), label='E')
        graph.add_node(e4_1, layer=1, position=(0.0, 1.0), label='E')

        graph.add_edge(e1_1, e2_1)
        graph.add_edge(e1_1, e3_1)
        graph.add_edge(e1_1, e4_1)
        graph.add_edge(e2_1, e3_1)
        graph.add_edge(e3_1, e4_1)

        i1_1 = add_interior(graph, e1_1, e2_1, e3_1)
        i2_1 = add_interior(graph, e1_1, e3_1, e4_1)
        graph.nodes[i1_1]['label'] = 'i'
        graph.nodes[i2_1]['label'] = 'i'

        e1_2, e2_2, e3_2, e4_2, e5_2 = [gen_name() for _ in range(5)]
        graph.add_node(e1_2, layer=2, position=(0.0, 0.0), label='E')
        graph.add_node(e5_2, layer=2, position=(0.0, 0.0), label='E')
        graph.add_node(e2_2, layer=2, position=(1.0, 0.0), label='E')
        graph.add_node(e3_2, layer=2, position=(0.5, 0.5), label='E')
        graph.add_node(e4_2, layer=2, position=(0.0, 1.0), label='E')

        graph.add_edge(e1_2, e2_2)
        graph.add_edge(e1_2, e3_2)
        graph.add_edge(e5_2, e4_2)
        graph.add_edge(e5_2, e3_2)
        graph.add_edge(e2_2, e3_2)
        graph.add_edge(e3_2, e4_2)

        i1_2 = add_interior(graph, e1_2, e2_2, e3_2)
        i2_2 = add_interior(graph, e5_2, e3_2, e4_2)

        graph.add_edge(i1_1, i1_2)
        graph.add_edge(i2_1, i2_2)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()

        P13().apply(graph, [i1_1, i2_1, i1_2, i2_2])

        # based on test_p12
        # if correct number of nodes and edges
        self.assertEqual(len(graph.nodes()), 12)
        self.assertEqual(len(graph.edges()), 24)

        # if interiors has correct labels, layers and are connected
        self.assertEqual(graph.nodes[i1_1]['label'], 'i')
        self.assertEqual(graph.nodes[i2_1]['label'], 'i')
        self.assertEqual(graph.nodes[i1_1]['layer'], 1)
        self.assertEqual(graph.nodes[i2_1]['layer'], 1)
        self.assertEqual(graph.nodes[i1_2]['label'], 'I')
        self.assertEqual(graph.nodes[i2_2]['label'], 'I')
        self.assertEqual(graph.nodes[i1_2]['layer'], 2)
        self.assertEqual(graph.nodes[i2_2]['layer'], 2)
        self.assertTrue(graph.has_edge(i1_1, i1_2))
        self.assertTrue(graph.has_edge(i2_1, i2_2))

        # if each interior has 3 neighbors on the corresponding layer
        i1_1_neighbors = get_neighbors_at(graph, i1_1,
                                          graph.nodes[i1_1]['layer'])
        self.assertEqual(len(i1_1_neighbors), 3)
        i2_1_neighbors = get_neighbors_at(graph, i2_1,
                                          graph.nodes[i2_1]['layer'])
        self.assertEqual(len(i2_1_neighbors), 3)
        i1_2_neighbors = get_neighbors_at(graph, i1_2,
                                          graph.nodes[i1_2]['layer'])
        self.assertEqual(len(i1_2_neighbors), 3)
        i2_2_neighbors = get_neighbors_at(graph, i2_2,
                                          graph.nodes[i2_2]['layer'])
        self.assertEqual(len(i2_2_neighbors), 3)

        # if nodes in lower layer exists and are correctly connected
        new_e1_2 = get_node_at(graph, 2, (0.0, 0.0))
        new_e2_2 = get_node_at(graph, 2, (1.0, 0.0))
        new_e3_2 = get_node_at(graph, 2, (0.5, 0.5))
        new_e4_2 = get_node_at(graph, 2, (0.0, 1.0))
        self.assertIsNotNone(new_e1_2)
        self.assertIsNotNone(new_e2_2)
        self.assertIsNotNone(new_e3_2)
        self.assertIsNotNone(new_e4_2)
        self.assertTrue(graph.has_edge(new_e1_2, new_e2_2))
        self.assertTrue(graph.has_edge(new_e1_2, new_e3_2))
        self.assertTrue(graph.has_edge(new_e1_2, new_e4_2))
        self.assertTrue(graph.has_edge(new_e2_2, new_e3_2))
        self.assertTrue(graph.has_edge(new_e3_2, new_e4_2))

        # if lower interiors connect with all 4 vertices
        all_neighbors = i1_2_neighbors + i2_2_neighbors
        all_neighbors = list(dict.fromkeys(all_neighbors))  # remove duplicates
        self.assertEqual(len(all_neighbors), 4)

        # if each vertex has correct label
        for n in all_neighbors:
            self.assertEqual(graph.nodes[n]['label'], 'E')

        # if each vertex has correct number of neighbors (based on neighbour interiors count)
        for n in all_neighbors:
            node_neighbors = get_neighbors_at(graph, n,
                                              graph.nodes[n]['layer'])
            i_neighbors = [
                x for x in node_neighbors if graph.nodes[x]['label'] == 'I'
            ]
            if len(i_neighbors) == 1:
                self.assertEqual(len(node_neighbors), 3)
            elif len(i_neighbors) == 2:
                self.assertEqual(len(node_neighbors), 5)
            else:
                self.assertEqual(len(node_neighbors), 7)

        if visualize_tests:
            visualize_graph_3d(graph)
            pyplot.show()