def solve(self) -> TspSolver: vertices_base = deepcopy(self.vertices()) for vertices in permutations(vertices_base): edges = [] solution = 0.0 u = vertices[0] for v in vertices[1:]: w = distance_vertex(u, v) edges.append(Edge(u, v, w)) solution += w u = v v = vertices[0] w = distance_vertex(u, v) edges.append(Edge(u, v, w)) solution += w if solution < self.__solution: self.__solution = solution self.__edges = edges graph = self.graph() for edge in self.__edges: graph.add_edge(edge) return self
def _add_edge(self, edge: Edge) -> Graph: vertex1, vertex2 = edge.vertices() weight = edge.weight() AdjListGraph._insert_into_adjlist(vertex1, vertex2, weight, self._adjlist()) AdjListGraph._insert_into_adjlist(vertex2, vertex1, weight, self.__transpose_adj_list) return self
def __is_crossed_edge( self, candidate: Edge, ): for edge in self.__edge_stack[1:]: line0 = (edge.source_vertex().coordinate(), edge.destination_vertex().coordinate() ) # Line segment edge list line1 = (candidate.source_vertex().coordinate(), candidate.destination_vertex().coordinate() ) # Line segment candidate edge if intersects(line0, line1): return True return False
def add_edge(self, edge: Edge) -> "Graph": """Add an edge in the graph and returns itself for chaining""" if self.__vgraph: u, v = edge.vertices() self.__vgraph.add_edge(u.id(), v.id()) self.__edge_count += 1 return self._add_edge(edge)
def solve(self) -> TspSolver: self.__solution = 0.0 graph = self.graph() vertices = self.vertices() src_vertex = vertices[0] next = src_vertex for v in vertices[1:]: distance = distance_vertex(next, v) graph.add_edge(Edge(next, v)) next = v self.__solution += distance distance = distance_vertex(next, src_vertex) graph.add_edge(Edge(next, src_vertex)) self.__solution += distance return self
def __build_complete_graph(self) -> None: vertices = self.vertices() for i in range(len(vertices)): for j in range(i): u = vertices[i] v = vertices[j] u[ADDED_KEY] = False v[ADDED_KEY] = False self.__complete_graph.add_vertex(u) self.__complete_graph.add_vertex(v) self.__complete_graph.add_edge( Edge(u, v, distance_vertex(u, v)))
def __find_path(self, before: Vertex, current: Vertex, is_keeping_direction: FunctionType) -> float: current[ADDED_KEY] = True self.__remaining_vertices -= 1 graph = self.graph() if current != self.__further_west and self.__is_crossed_edge( Edge(before, current)): current[ADDED_KEY] = False self.__remaining_vertices += 1 return float('inf') elif self.__remaining_vertices == 0 and current == self.__further_west: # found the solution! w = distance_vertex(current, before) graph.add_edge(Edge(before, current, w)) return w else: self.__edge_stack.insert(0, Edge(before, current)) if current == self.__further_east: predicate = self.__is_left_direction # change the direction else: predicate = is_keeping_direction # keep the direction (starts following right direction from further_west) for next in self.__complete_graph.neighborhood(current): x0 = current.coordinate()[0] x1 = next.coordinate()[0] if not next[ADDED_KEY] and predicate(x0, x1): cost = self.__find_path(current, next, predicate) if cost != float('inf'): w = distance_vertex(current, before) graph.add_edge(Edge(before, current, w)) return w + cost current[ADDED_KEY] = False self.__remaining_vertices += 1 self.__edge_stack.pop(0) return float('inf')