def main(): """Solve the CVRP problem.""" # Instantiate the data problem. data = create_data_model() # compute_geometry.load_config() # use specified demand factor demand_factor_range = [input_data["options"]["demand_factor"]] print("using default demand factor: ", list(demand_factor_range)) geometry.init_random(False) for i_df, df in enumerate(demand_factor_range): data['demands'] = [int(d) * df for d in input_data["demands"]] routes_vect = [] data['distance_matrix'] = compute_geometry.compute_distance_matrix_wrapper() # Create the routing index manager. # manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), # data['num_vehicles'], data['depot']) manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['starts'], data['ends']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def distance_callback(from_index, to_index): """Returns the distance between the two nodes.""" # Convert from routing variable Index to distance matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data['distance_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback( distance_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Capacity constraint. def demand_callback(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) return data['demands'][from_node] demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) routing.AddDimensionWithVehicleCapacity( demand_callback_index, 0, # null capacity slack data['vehicle_capacities'], # vehicle maximum capacities True, # start cumul to zero 'Capacity') # Add the maximum distance travel constraint for each vehicle: routing.AddDimensionWithVehicleCapacity( transit_callback_index, 0, # null capacity slack # vehicle fuel / max daily/travel distance data['vehicle_fuel'], True, # start cumul to zero 'DailyDistance') # Allow to drop nodes. penalty = 10000 for node in range(1, len(data['distance_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], penalty) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # search_parameters.first_solution_strategy = ( # routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) time_limit = 1 search_parameters.time_limit.FromSeconds(time_limit) # Total Distance of all routes: 18041m # Total Load of all routes: 47 print("running solver max time limit: " + str(time_limit)) print(coords[len(vehicles):]) print(len(coords[len(vehicles):])) print(vehicles) # quit() # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) if assignment: # Print solution on console. routes = plot_routes.print_solution( data, manager, routing, assignment) print('The Objective Value is {0}'.format(assignment.ObjectiveValue())) # you could print debug information like this: # print(routing.DebugOutputAssignment(assignment, 'Capacity')) vehicle_routes = {} for veh in range(len(vehicles)): vehicle_routes[veh] = build_vehicle_route(manager, routing, assignment, coords, veh) print(vehicle_routes) # quit() # coords[len(vehicles):] fig = plotter.plot_vehicle_routes_wrapper(vehicle_routes,coords,data['starts'],data['ends'],0.1) fig.savefig("figs/routes.png", dpi=300)
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. data = create_data_model() # compute_geometry.load_config() n_iter = input_data["options"]["n_iter"] if input_data["options"]["use_range"]: # use demand factor range demand_factor_range = input_data["options"]["demand_factor_range"] demand_factor_range = range(demand_factor_range[0], demand_factor_range[1] + 1) print("using demand factor range: ", list(demand_factor_range)) else: # use specified demand factor demand_factor_range = [input_data["options"]["demand_factor"]] print("using default demand factor: ", list(demand_factor_range)) geometry.init_random(False) for i_df, df in enumerate(demand_factor_range): data['demands'] = [int(d) * df for d in input_data["demands"]] routes_vect = [] for i in range(n_iter): if i == 0: data[ 'distance_matrix'] = compute_geometry.compute_distance_matrix_wrapper( ) else: data[ 'distance_matrix'] = compute_geometry.get_distance_matrix_with_random_depots( ) print("iteration: " + str(i) + " with demand factor: " + str(df) + " [" + str( int((i_df * n_iter + i) / (len(demand_factor_range) * n_iter) * 100)) + "%]") # Create the routing index manager. # manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), # data['num_vehicles'], data['depot']) manager = pywrapcp.RoutingIndexManager( len(data['distance_matrix']), data['num_vehicles'], data['starts'], data['ends']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def distance_callback(from_index, to_index): """Returns the distance between the two nodes.""" # Convert from routing variable Index to distance matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data['distance_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback( distance_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Capacity constraint. def demand_callback(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) return data['demands'][from_node] demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) routing.AddDimensionWithVehicleCapacity( demand_callback_index, 0, # null capacity slack data['vehicle_capacities'], # vehicle maximum capacities True, # start cumul to zero 'Capacity') # Add the maximum distance travel constraint for each vehicle: routing.AddDimensionWithVehicleCapacity( transit_callback_index, 0, # null capacity slack # vehicle fuel / max daily/travel distance data['vehicle_fuel'], True, # start cumul to zero 'DailyDistance') # Allow to drop nodes. penalty = 10000 for node in range(1, len(data['distance_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], penalty) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # search_parameters.first_solution_strategy = ( # routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) time_limit = 1 search_parameters.time_limit.FromSeconds(time_limit) # Total Distance of all routes: 18041m # Total Load of all routes: 47 print("running solver max time limit: " + str(time_limit)) # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) # Print solution on console. if assignment: routes = plot_routes.print_solution(data, manager, routing, assignment) routes_vect.append(routes) print(routes) disp_routes = json.dumps(routes_vect) with open("data/routes_sim." + str(df) + ".txt", "w") as f: f.write(disp_routes) with open("data/routes_sim_info." + str(df) + ".txt", "w") as f: sim_info = {"demand_factor": df} f.write(json.dumps(sim_info))
def main(): # Instantiate the data problem. config, input_data, coords, dm = config_loader.load_config() depots = input_data["depots"] places = input_data["places"] vehicles = input_data["vehicles"] n_vehicles = len(vehicles) options = input_data["options"] # just for initial check demands = [ int(d) * options["demand_factor"] for d in input_data["demands"] ] vehicle_capacities = [int(v["capacity"]) for v in vehicles] vehicle_fuel = [int(v["fuel"]) for v in vehicles] items = options["items"] if options["fixed_vehicles"]: n_vehicles = options["n_vehicles"] vehicles = [{"id": i + 1} for i in range(n_vehicles)] print(items) if options["sort_order_msb"]: items.sort(key=lambda x: x["weight"], reverse=True) print(items) sum_demands = sum(demands) sum_capacities = sum(vehicle_capacities) depot = 0 # So far, we have assumed that all vehicles start and end at a single location, the depot. # You can also set possibly different start and end locations for each vehicle in the problem. # To do so, pass two vectors, containing the indices of the start and end locations, # as inputs to the RoutingModel method in the main function. # Here's how to create the start and end vectors in the data section of the program: start_points = [i for i in range(len(depots))] end_points = [i for i in range(len(depots))] print("sum demands: " + str(sum_demands)) print("sum capacities: " + str(sum_capacities)) # compute_geometry.load_config() n_iter = options["n_iter"] n_epochs = options["n_epochs"] if use_external_input: df = pd.read_csv('coords_nearby_filtered.csv') place_ids = [] coords = [] place_ids = df["google_id"] coords_lat = [lat for lat in df["lat"]] coords_lng = [lng for lng in df["lng"]] for i in range(len(coords_lat)): coords.append([coords_lat[i], coords_lng[i]]) place_ids = ["place_id:" + pid for pid in place_ids] print(place_ids[0]) print(coords[0]) places = place_ids[n_vehicles:] if options["fixed_demands"]: # only use demand factor input_data["demands"] = [1 for p in place_ids] place_coords = coords[n_vehicles:] compute_geometry.set_coords(coords) # quit() if options["use_range"]: # use demand factor range demand_factor_range = options["demand_factor_range"] demand_factor_range = range(demand_factor_range[0], demand_factor_range[1] + 1) print("using demand factor range: ", list(demand_factor_range)) else: # use specified demand factor demand_factor_range = [options["demand_factor"]] print("using default demand factor: ", list(demand_factor_range)) geometry.init_random(False) epoch_results_vect = [] for epoch in range(n_epochs): for i_df, df in enumerate(demand_factor_range): demands = [int(d) * df for d in input_data["demands"]] demands = demands[n_vehicles:] fill_dict = {} for i, place in enumerate(places): fill_dict[place] = { "place": place, "coords": place_coords[i], "items": [], "item_coords": [], "found": False, "filled": False, "finder": None, "find_index": -1, "total_revisits": 0, "demand": demands[i] } print(len([k for k in fill_dict])) find_index = 0 compute_geometry.init_random_walk(vehicles, None) for i in range(n_iter): if i == 0 and use_initial_depots: distance_matrix = compute_geometry.compute_distance_matrix_wrapper( ) else: distance_matrix = compute_geometry.get_distance_matrix_with_random_walk( ) print("epoch: " + str(epoch) + ", iteration: " + str(i) + " with demand factor: " + str(df) + " [" + str( int((i_df * n_iter + i) / (len(demand_factor_range) * n_iter) * 100)) + "%]") # each agent covers a given range (treasure scan) for i_vehicle, v in enumerate(vehicles): if disp_view: print("vehicle: ", i_vehicle) # check nearby places within range found_places = [] for j, d in enumerate(distance_matrix[i_vehicle]): if j >= n_vehicles: # print(j,d) if d <= options["scan_radius"]: if disp_view: print("found: ", d) place = places[j - n_vehicles] dict_place = fill_dict[place] # check if place was already found by another agent if not dict_place["found"]: dict_place["found"] = True dict_place["finder"] = vehicles[i_vehicle][ "id"] dict_place["find_index"] = find_index found_places.append(dict_place) find_index += 1 else: dict_place["total_revisits"] += 1 if disp_view: print("already found: ", d) # assign random items for each agent and found places n_slots = 0 for fps in found_places: # check filled items, get number of free slots if not fps["filled"]: n_slots += fps["demand"] if disp_view: print("n_slots: ", n_slots) # generate free slots slots = [None] * n_slots n_items = [] # compute number of slots for each item type for item in items: n_items.append(int(n_slots * item["weight"])) # assign items for free slots slots_index = 0 for k, n_item in enumerate(n_items): for n in range(n_item): slots[slots_index] = items[k]["item"] slots_index += 1 if disp_view: print("n_items: ", n_items) print("filled: ", slots_index) # check unfilled slots, fill with last item type n_unfilled = n_slots - slots_index if slots_index < n_slots: for n in range(n_unfilled): slots[slots_index + n] = items[len(items) - 1]["item"] # shuffle items/slots slots = shuffle.fisher_yates_shuffle_improved(slots) if disp_view: print(len(slots)) slots_index = 0 # assign items to actual places for fps in found_places: for d in range(fps["demand"]): if not fps["filled"]: fps["items"].append(slots[slots_index]) fps["item_coords"].append( geometry.get_random_point_in_radius( fps["coords"], options["item_coords"]["min_radius"], options["item_coords"]["max_radius"])) slots_index += 1 else: if disp_view: print("already filled") if check_results(items, places, demands, fill_dict, i, epoch, False, True)[0]: break _, epoch_results, map_geometry = check_results( items, places, demands, fill_dict, i, epoch, True, False) epoch_results_vect.append(epoch_results) fig = compute_geometry.plot_random_walk_record() output_str = "epoch,places,demand,T,C,S,A,revisits,iterations\n" for epoch_results in epoch_results_vect: output_str += epoch_results + "\n" print(output_str) with open("./data/dms_results.csv", "w") as f: f.write(output_str) map_geometry_str = json.dumps(map_geometry, indent=2) with open("./data/dms_map.json", "w") as f: f.write(map_geometry_str) fig.savefig("./data/random_walk.png", dpi=300)
for i in range(n_vehicles): new_coords[i] = geometry.get_random_point_in_radius( center_point, 0, max_dist_from_center) return new_coords def main(): """main function: compute distance matrix for given coords""" d_mat = compute_distance_matrix(coords) print(d_mat) with open(config["matrix_file"], "w") as file: for row in d_mat: file.write(",".join([str(e) for e in row]) + "\n") def get_distance_matrix_with_random_depots(): new_coords = compute_random_points(coords) d_mat = compute_distance_matrix(new_coords) return d_mat if __name__ == "__main__": # main() geometry.init_random(False) d_mat = compute_distance_matrix(coords) print(d_mat) d_mat = get_distance_matrix_with_random_depots() print(d_mat)