Example #1
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 []
Example #2
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
Example #3
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 []
Example #4
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')
Example #5
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')
Example #6
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