def brute_force_solution(graph, current_vertex_id=1, reduce_ram_usage=False): # Generate route log path if reduce_ram_usage: route_log_path =os.getcwd() + os.path.sep + ".." + os.path.sep + "logs" + os.path.sep + \ "RouteLog_{0}_{1}".format(len(graph.vertices), str(time.time())[:9]) # Recursive function for trying all adjacent vertices. def try_all_open_routes_from_current_route(route, reduce_ram_usage=False): # Initialize Routes to keep track of all attempted routes. routes = np.array([]) # Start at the current vertex id location current_vertex = route.graph.vertices[current_vertex_id] # For each adjacent vertex that has not been visited for adjacent_vertex in current_vertex.get_unvisited_adjacent_vertex_ids( ): # copy the route so far new_route = deepcopy(route) # goto the current adjacent_vertex new_route.goto(adjacent_vertex.vertex_id) # if all vertices have been visisted if new_route.graph.finished(): # goto the current vertex id new_route.goto(current_vertex_id) if reduce_ram_usage: # Log finished route to hard disk FileHandler.log_route(new_route, route_log_path) # Delete from RAM del new_route else: # append the route to the list of completed routes routes = np.concatenate((routes, new_route), axis=None) else: # if not, if reduce_ram_usage: try_all_open_routes_from_current_route( new_route, reduce_ram_usage) else: # Recall the recursive function using the updated route. routes = np.concatenate(( routes, try_all_open_routes_from_current_route(new_route)), axis=None) # After all adjacent vertices have been visisted recursively, return the list of routes return routes # Initialize the route route = Route(list([]), graph) # goto the current vertex id route.goto(current_vertex_id) # Initialize a list of routes routes = np.array([]) # Recursively try all open routes from the current route, advancing when possible. routes = np.concatenate( (routes, try_all_open_routes_from_current_route( route, reduce_ram_usage=reduce_ram_usage)), axis=None) if reduce_ram_usage: del routes # Sift file located at route_log_path for the shortest route return FileHandler.find_minimum_route(route_log_path) else: # Identify the route with minimum distance traveled return min(routes)
class GreedyAlgorithm(object): def __init__(self, graph, starting_vertex_id=1, reset_heuristic=False): self.route = Route(graph) self.starting_vertex_id = starting_vertex_id self.route.goto( self.route.graph.get_vertex_by_id(starting_vertex_id)) self.done = False self.attempted_starting_vertex_ids = list([starting_vertex_id]) self.remaining_starting_vertex_ids = self.get_remaining_starting_vertex_ids( ) self.reset_heuristic = reset_heuristic self.crosses = 0 def __eq__(self, other): return self.route.distance_traveled == other.route.distance_traveled def __lt__(self, other): return self.route.distance_traveled < other.route.distance_traveled def __le__(self, other): return self.route.distance_traveled <= other.route.distance_traveled def __gt__(self, other): return self.route.distance_traveled > other.route.distance_traveled def __ge__(self, other): return self.route.distance_traveled >= other.route.distance_traveled def __str__(self): string = "Starting vertex id: " + str( self.starting_vertex_id) + "\n" string += "Route: " + str(self.route) + "\n" string += "reset_heuristic: " + str(self.reset_heuristic) + "\n" string += "Crosses: " + str(self.crosses) return string def complete(self): while not self.done: self.step_forward() return self.route def step_forward(self): next_vertex, closest_item_next_to_vertex = self.choose_next_vertex( ) self.route.lasso(next_vertex, closest_item_next_to_vertex) if len(self.route.vertices) > len(self.route.graph.vertices): self.done = True def step_backward(self): if len(self.route.vertices) > 0: self.route.walk_back() self.attempted_starting_vertex_ids.pop() self.remaining_starting_vertex_ids = self.get_remaining_starting_vertex_ids( ) if self.done: self.done = False def choose_next_vertex(self): closest_item_next_to_closest_vertex = None r_type_of_closest_item = None closest_vertex = None closest_distance = None for vertex in self.route.get_unvisited_vertices(): closest_item_next_to_vertex, item_distance = self.route.get_shortest_distance_to_route( vertex) if closest_vertex is None: closest_vertex = vertex closest_distance = item_distance closest_item_next_to_closest_vertex = closest_item_next_to_vertex else: if item_distance < closest_distance: closest_distance = item_distance closest_vertex = vertex closest_item_next_to_closest_vertex = closest_item_next_to_vertex if len(self.route.get_unvisited_vertices()) == 0: return self.route.vertices[0], self.route.vertices[1] else: return closest_vertex, closest_item_next_to_closest_vertex def get_remaining_starting_vertex_ids(self): return [ vertex_id for vertex_id in list( range(1, len(self.route.graph.vertices) + 1)) if vertex_id not in self.attempted_starting_vertex_ids ]