Пример #1
0
    def __init__(self, N, G_in=None, init_empty=False):
        G.__init__(self, N, G_in=G_in)
        self.hash_value = None

        if not init_empty:
            if G_in is None:
                G.new_vertex_property(self,
                                      "orientation",
                                      dtype="vector<double>")
                G.new_vertex_property(self, "position", dtype="vector<double>")
                G.new_vertex_property(self, "partner", dtype="long long")

                G.new_vertex_property(self,
                                      "selected",
                                      dtype="bool",
                                      value=False)
                G.new_vertex_property(self,
                                      "solved",
                                      dtype="bool",
                                      value=False)
                G.new_edge_property(self,
                                    "selected",
                                    dtype="bool",
                                    value=False)
                G.new_edge_property(self, "solved", dtype="bool", value=False)
                G.new_edge_property(self,
                                    "edge_cost",
                                    dtype="double",
                                    value=0.0)

                for v in G.get_vertex_iterator(self):
                    self.set_partner(v, -1)

        # NOTE: Start/End dummy node and edge are implicit
        self.edge_index_map = G.get_edge_index_map(self)
Пример #2
0
    def get_edge_combination_cost_curvature(self,
                                            comb_angle_factor,
                                            comb_angle_prior=0.0,
                                            return_edges_to_middle=False):

        edge_index_map = G.get_edge_index_map(self)
        """
        Only collect the indices for each edge combination in
        the loop and perform cost calculation later in vectorized 
        form.
        """
        middle_indices = []
        edges_to_middle = {}
        end_indices = []
        edges = []
        cost = []
        prior_cost = {}
        edge_combination_cost = {}
        """
        Problem: The indices are derived from the vertices in the graph.
        The graphs are filtered versions of a bigger graph where the
        vertices have not been enumerated newly. Thus we expect 
        vertices to have random indices, not corresponding to 
        the number of vertices in the sub graph. If we try to acces
        the position matrix with these indices we get out of bounds
        errors because the position matrix has only the entries 
        of the filtered subgraph. We need to map vertex indices
        in the range [0, N_vertices_subgraph - 1]
        """

        index_map = {}

        for n, v in enumerate(G.get_vertex_iterator(self)):
            incident_edges = G.get_incident_edges(self, v)
            index_map[v] = n

            for e1 in incident_edges:
                for e2 in incident_edges + [self.START_EDGE]:
                    e1_id = self.get_edge_id(e1, edge_index_map)
                    e2_id = self.get_edge_id(e2, edge_index_map)

                    if e1_id >= e2_id and e2_id != self.START_EDGE.id():
                        continue

                    if e2_id == self.START_EDGE.id():
                        """
                        Always append edges together with cost
                        s.t. zip(edges, cost) is a correct mapping
                        of edges to cost.
                        """
                        prior_cost[(e1, e2)] = comb_angle_prior
                        edges_to_middle[(e1, e2)] = int(v)

                    else:
                        """
                        Here we only save indices. How to secure
                        a proper matching between cost that we calculate
                        later and the corresponding edges?

                        1. Middle vertex is v -> index_map[v] in [0, N-1]
                        2. Append the middle_vertex twice to a list.
                        3. Append the distinct end vertices (2) to end vertices
                        4. Append the corresponding edges to a list.

                        -> We end up with 3 lists of the following form:
                        edges = [(e1, e2), (e3, e4), ...]
                        m_ind = [ m1, m1 ,  m2, m2 , ...]
                        e_ind = [ v1, v2 ,  v3, v4 , ...]
                        p_arr = [ p(m1)  ,   p(m2) , ...]
                        index_map: m1 -> 0, m2 -> 1, m3 -> 2, ...
                            --> p_arr[m1] = p(m1), p_arr[m2] = p(m2) 
                        """
                        middle_vertex = int(v)
                        middle_indices.extend([middle_vertex, middle_vertex])

                        end_vertices = [
                            int(e1.source()),
                            int(e1.target()),
                            int(e2.source()),
                            int(e2.target())
                        ]

                        end_vertices.remove(middle_vertex)
                        end_vertices.remove(middle_vertex)

                        ordered_points = [None, None, None]
                        ordered_points[0] = np.array(
                            self.get_position(end_vertices[0]))
                        ordered_points[2] = np.array(
                            self.get_position(end_vertices[1]))
                        ordered_points[1] = np.array(
                            self.get_position(middle_vertex))

                        energy = get_energy_from_ordered_points(ordered_points,
                                                                n_samples=1000)
                        edge_combination_cost[(e1,
                                               e2)] = (energy *
                                                       comb_angle_factor)**2

                        end_indices.extend(list(end_vertices))
                        edges.append((e1, e2))
                        edges_to_middle[(e1, e2)] = int(v)
                        """
                        (e1, e2) -> end_indices, middle_indices
                        """

        edge_combination_cost.update(prior_cost)
        logger.info("edge_combination_cost: " + str(edge_combination_cost))

        if return_edges_to_middle:
            return edge_combination_cost, edges_to_middle
        else:
            return edge_combination_cost
Пример #3
0
    def get_edge_combination_cost_angle(self,
                                        comb_angle_factor,
                                        comb_angle_prior=0.0,
                                        return_edges_to_middle=False):

        edge_index_map = G.get_edge_index_map(self)
        """
        Only collect the indices for each edge combination in
        the loop and perform cost calculation later in vectorized 
        form.
        """
        middle_indices = []
        edges_to_middle = {}
        end_indices = []
        edges = []
        cost = []
        prior_cost = {}
        """
        Problem: The indices are derived from the vertices in the graph.
        The graphs are filtered versions of a bigger graph where the
        vertices have not been enumerated newly. Thus we expect 
        vertices to have random indices, not corresponding to 
        the number of vertices in the sub graph. If we try to acces
        the position matrix with these indices we get out of bounds
        errors because the position matrix has only the entries 
        of the filtered subgraph. We need to map vertex indices
        in the range [0, N_vertices_subgraph - 1]
        """

        index_map = {}

        for n, v in enumerate(G.get_vertex_iterator(self)):
            incident_edges = G.get_incident_edges(self, v)
            index_map[v] = n

            for e1 in incident_edges:
                for e2 in incident_edges + [self.START_EDGE]:
                    e1_id = self.get_edge_id(e1, edge_index_map)
                    e2_id = self.get_edge_id(e2, edge_index_map)

                    if e1_id >= e2_id and e2_id != self.START_EDGE.id():
                        continue

                    if e2_id == self.START_EDGE.id():
                        """
                        Always append edges together with cost
                        s.t. zip(edges, cost) is a correct mapping
                        of edges to cost.
                        """
                        prior_cost[(e1, e2)] = comb_angle_prior
                        edges_to_middle[(e1, e2)] = int(v)

                    else:
                        """
                        Here we only save indices. How to secure
                        a proper matching between cost that we calculate
                        later and the corresponding edges?
                        1. Middle vertex is v -> index_map[v] in [0, N-1]
                        2. Append the middle_vertex twice to a list.
                        3. Append the distinct end vertices (2) to end vertices
                        4. Append the corresponding edges to a list.
                        -> We end up with 3 lists of the following form:
                        edges = [(e1, e2), (e3, e4), ...]
                        m_ind = [ m1, m1 ,  m2, m2 , ...]
                        e_ind = [ v1, v2 ,  v3, v4 , ...]
                        p_arr = [ p(m1)  ,   p(m2) , ...]
                        index_map: m1 -> 0, m2 -> 1, m3 -> 2, ...
                            --> p_arr[m1] = p(m1), p_arr[m2] = p(m2) 
                        """
                        middle_vertex = int(v)
                        middle_indices.extend([middle_vertex, middle_vertex])

                        end_vertices = set([
                            int(e1.source()),
                            int(e1.target()),
                            int(e2.source()),
                            int(e2.target())
                        ])

                        end_vertices.remove(middle_vertex)
                        end_indices.extend(list(end_vertices))
                        edges.append((e1, e2))
                        edges_to_middle[(e1, e2)] = int(v)
                        """
                        (e1, e2) -> end_indices, middle_indices
                        """

        if middle_indices:
            pos_array = self.get_position_array()
            end_indices = np.array([index_map[v] for v in end_indices])
            middle_indices = np.array([index_map[v] for v in middle_indices])

            v = (pos_array[:, end_indices] - pos_array[:, middle_indices]).T
            norm = np.sum(np.abs(v)**2, axis=-1)**(1. / 2.)
            u = v / np.clip(norm[:, None], a_min=10**(-8), a_max=None)
            angles = np.arccos(np.clip(inner1d(u[::2], u[1::2]), -1.0, 1.0))
            angles = np.pi - angles
            cost = cost + list((angles * comb_angle_factor)**2)

        edge_combination_cost = dict(itertools.izip(edges, cost))
        edge_combination_cost.update(prior_cost)

        if return_edges_to_middle:
            return edge_combination_cost, edges_to_middle
        else:
            return edge_combination_cost