def vrp_script(data, company_list, params, printer=False): # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) def time_callback(from_index, to_index): """Returns the travel time between the two nodes.""" # Convert from routing variable Index to time matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) # data['demands'] adds the loading time to the travel time return (data['loadtimes'][from_node] * 60) + data['distance_matrix'][from_node][to_node] 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') transit_callback_index = routing.RegisterTransitCallback(time_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) time = 'Time' routing.AddDimension( transit_callback_index, 500, # allow waiting time 14400, # maximum time per vehicle True, # Don't force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) # Add time window constraints for each vehicle start node. for vehicle_id in range(data['num_vehicles']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) for i in range(data['num_vehicles']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC) #GEBRUIK NU PATH_MOST_CONSTRAINED_ARC # sets the time limit in seconds search_parameters.time_limit.seconds = 5 # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) if assignment: if printer == True: list_of_routes, time = pt.print_solution(data, manager, routing, assignment, company_list) else: list_of_routes, time = pt.create_list_of_routes( data, manager, routing, assignment, company_list) return list_of_routes, time return 0, 0
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # [START distance_constraint] dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 3000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # [END distance_constraint] # [START print_initial_solution] initial_solution = routing.ReadAssignmentFromRoutes(data['initial_routes'], True) print('Initial solution:') print_solution(data, manager, routing, initial_solution) # [END print_initial_solution] # Set default search parameters. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveFromAssignmentWithParameters( initial_solution, search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print('Solution after search:') print_solution(data, manager, routing, solution)
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. data = create_data_model() # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # 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 Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 3500, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # Setting first solution heuristic wit time limit if solution not found search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.time_limit.seconds = 5 search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. if solution: print_solution(data, manager, routing, solution)
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. data = create_data_model() # Create the routing index manager. manager = pywrapcp.RoutingIndexManager( len(data['distance_matrix']), data['num_vehicles'], data['depot']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # ADD THE DISTANCE CALLBACK # ADD THE DEMAND CALLBACK AND CAPACITY COSTRAINTS # In addition to the distance callback, the solver also requires a demand callback, # which returns the demand at each location, and a dimension for the capacity constraints. # 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) #!!! NB # Unlike the distance callback, which takes a pair of locations as inputs, # the demand callback only depends on the location (from_node) of the delivery. # The code also creates a dimension for capacities, we use the AddDimensionWithVehicleCapacity method, # which takes a vector of capacities. # Since all the vehicle capacities in this example are the same, you could use the the # AddDimension method, which takes a single upper bound for all vehicle quantities. # But AddDimensionWithVehicleCapacity handles the more general case in which different # vehicles have different capacities. # 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, modify it if you accept unmet demand data['vehicle_capacities'], # vehicle maximum capacities set by the user True, # start cumul to zero 'Capacity') # you can find other research method here: # https://developers.google.com/optimization/routing/routing_options # Setting first solution heuristic: search_parameters = pywrapcp.DefaultRoutingSearchParameters() # search_parameters.first_solution_strategy = ( # routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # Setting metaheuristic search method: search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) # Setting time limit to the method search_parameters.time_limit.seconds = 30 # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) # Search status print('\n') solver_index = routing.status() description = ['ROUTING_NOT_SOLVED','ROUTING_SUCCESS','ROUTING_FAIL', 'ROUTING_FAIL_TIMEOUT','ROUTING_INVALID'] print("Solver status:",description[solver_index],'\n') # Print solution on console. if assignment: print_solution(data, manager, routing, assignment)
def optimize(self): # find max z: maxZTarget = 0 units = None for line in self.data.gcode: line = stripComments(line) gString = line[line.find("G"): line.find("G") + 3] if gString == "G21": if units is not None and units != "G21": print("Error, units switch in file") return False units = "G21" if gString == "G20": if units is not None and units != "G20": print("Error, units switch in file") return False units = "G20" if gString == "G00" or gString == "G0 ": #found G0/G00 zTarget = getZFromGCode(line) if zTarget is not None: if float(zTarget) > float(maxZTarget): maxZTarget = zTarget pathList = [] inPath = False index = 0 startLine = 0 startX = None startY = None currentX = None currentY = None inHeader = True headerEnd = 0 tool = 0 toolList = [0] footerStart = 0 #path list will hold the parsed gcode groups between G0 moves. for line in self.data.gcode: line = stripComments(line) tString = findInLine(line, "T", 2) # search for tool command if len(tString) > 1: toolVal = getNumberAfterCode(line, "T") toolVal = int(toolVal) print(line) print(toolVal) if toolVal != tool: if inPath: #close off current path endX = currentX endY = currentY pathList.append( Path(x0=startX, y0=startY, x1=endX, y1=endY, startLine=startLine, finishLine=index, tool=tool)) #currentX, currentY = getXYFromGCode(line, currentX, currentY) #there won't be a currentX, currentY in this code inPath = False toolList.append(toolVal) tool = toolVal print("Current tool is now: "+str(tool)) gString = findInLine(line, "G", 3) if True: if gString == "G00" or gString == "G0 ": #found G0/G00 if not inPath: if currentX is None and currentY is None: startX, startY = getXYFromGCode(line, currentX, currentY) currentX = startX currentY = startY inHeader = False else: startX = currentX startY = currentY endX, endY = getXYFromGCode(line, currentX, currentY) currentX = endX currentY = endY inHeader = False else: endX = currentX endY = currentY pathList.append(Path(x0=startX, y0=startY, x1=endX,y1=endY, startLine=startLine, finishLine=index, tool=tool)) currentX, currentY = getXYFromGCode(line, currentX, currentY) inPath = False elif gString == "G01" or gString == "G1 " or gString == "G02" or gString == "G2 " or gString == "G03" or gString == "G3 ": #found G1/G01/G2/G02/G3/G03 endX, endY = getXYFromGCode(line, currentX, currentY) if startX is None or startY is None: headerEnd = index else: if not inPath: startLine = index startX = currentX startY = currentY if endX is None: endX = startX if endY is None: endY = startY currentX = endX currentY = endY inPath = True inHeader = False else: if inHeader: headerEnd = index #print(line) #print(str(inPath)+"=>"+ str(startX) + ", " + str(startY)+" - "+str(currentX) + ", " + str(currentY)) index = index + 1 #print("last"+str(inPath)+"=>"+ str(startX) + ", " + str(startY)+" - "+str(currentX) + ", " + str(currentY)) newGCode = [] newGCode.append(units) for i in range(0, headerEnd+1): line = self.data.gcode[i] gString = line[line.find("G"): line.find("G") + 3] if gString != "G21" and gString != "G20": # don't setup units anymore newGCode.append(self.data.gcode[i]) #repeat for each tool: print("ToolList") print(toolList) for tool in toolList: """Entry point of the program.""" # Instantiate the data problem. newGCode.append("M6 T"+str(tool)) data = create_data_model(pathList, tool) if len(data['locations']) > 0: #could be nulled out because first tool is not 0 manager = pywrapcp.RoutingIndexManager(len(data['locations']), data['num_vehicles'], data['depot']) routing = pywrapcp.RoutingModel(manager) distance_matrix = compute_euclidean_distance_matrix(data['locations']) 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 distance_matrix[from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(distance_callback) routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) solution = routing.SolveWithParameters(search_parameters) if solution: print_solution(manager, routing, solution) """Prints solution on console.""" index = routing.Start(0) route_distance = 0 while not routing.IsEnd(index): pathIndex = manager.IndexToNode(index) startLine = data['locations'][pathIndex][4] finishLine = data['locations'][pathIndex][5] newGCode.append("G0 Z" + str(maxZTarget)) newGCode.append("G0 X" + str(data['locations'][pathIndex][0]) + " Y" + str(data['locations'][pathIndex][1])) line = self.data.gcode[startLine] gString = line[line.find("G"): line.find("G") + 3] if gString == "G01" or gString == "G1 ": # found G0/G00 X, Y = getXYFromGCode(line, None, None) if X is None and Y is None: zTarget = getZFromGCode(line) if float(zTarget) < 0: newGCode.append("G0 Z0.5") for i in range(startLine, finishLine): newGCode.append(self.data.gcode[i]) previous_index = index index = solution.Value(routing.NextVar(index)) route_distance += routing.GetArcCostForVehicle(previous_index, index, 0) else: print("No locations for tool"+str(tool)) newGCode.append("G0 Z" + str(maxZTarget)) newGCode.append("G0 X" + str(currentX) + " Y" + str(currentY)) print('Objective: {} units\n'.format(solution.ObjectiveValue()/100)) print('Path distance: {} units\n'.format(route_distance/100)) ''' for path in bestRoute: newGCode.append("G0 Z" + str(maxZTarget)) newGCode.append("G0 X" + str(path.x0) + " Y" + str(path.y0)) #print("G0 Z" + str(maxZTarget)) #print("G0 X" + str(path.x0) + " Y" + str(path.y0)) for i in range(path.startLine, path.finishLine ): newGCode.append(self.data.gcode[i]) #print(self.data.gcode[i]) ''' finalGCode = "" for i in newGCode: finalGCode = finalGCode + i + "\n" self.data.actions.updateGCode(finalGCode) return True
def optimize(self, data, manager, routing): def make_time_callbacks(vehicle_ind): def time_callback(from_index, to_index): """Returns the travel time between the two nodes.""" # Convert from routing variable Index to time matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) result = data['time_matrices'][vehicle_ind][from_node][to_node] # print( # f"time_callback: from_node: {from_node}, to_node: {to_node}, result: {result}") return result return time_callback def make_cost_callback(vehicle_ind): def cost_callback(from_index, to_index): from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) result = data["cost_matrixes"][vehicle_ind][from_node][to_node] # print( # f"cost_callback: from_node: {from_node}, to_node: {to_node}, result: {result}") return result return cost_callback def make_draft_callback(vehicle_ind): def draft_callback(to_index, from_index): # NON_CARGO_WEIGHT = 2500 # dwt = 4000 # comes from vessel description # immersion_summer = 200000 # comes from vessel description # draft = 100 # comes from vessel description # if from_index == 0: # # This gets hit multiple times # print(f"hitting from_index_0, {vehicle_ind}") # return data["vessel_empty_draft"][vehicle_ind] # if from_index == -1: # print( # f"setting the default draft: {vehicle_ind} to {data['vessel_empty_draft'][vehicle_ind]}") # return data["vessel_empty_draft"][vehicle_ind] from_node = manager.IndexToNode(from_index) cargo = data["draft_demands"][from_node] # dwt = data["dwt"][vehicle_ind] immersion_summer = data["immersion_summer"][vehicle_ind] # draft = data["draft"][vehicle_ind] # cargo_capacity = dwt - NON_CARGO_WEIGHT # cargo_capacity_unused = cargo_capacity - cargo_on_board centimeter_change_in_draft = cargo / immersion_summer # This does not work because call back is called many times # if vehicle_ind not in self.vessel_draft_set: # centimeter_change_in_draft += data["vessel_empty_draft"][vehicle_ind] # self.vessel_draft_set[vehicle_ind] = True # print( # f"vehicle_ind: {vehicle_ind}: change in draft: {centimeter_change_in_draft}") return centimeter_change_in_draft return draft_callback def make_draft_callback_2(vehicle_ind): def draft_callback(to_index, from_index): to_node = manager.IndexToNode(to_index) cargo = data["draft_demands"][to_node] immersion_summer = data["immersion_summer"][vehicle_ind] centimeter_change_in_draft = cargo / immersion_summer return centimeter_change_in_draft return draft_callback def volume_demand_callback(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) # print(f"volume demand: {data['volume_demands'][from_node]}") return data['volume_demands'][from_node] def weight_demand_callback(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) # print(f"weight demand: {data['volume_demands'][from_node]}") return data['weight_demands'][from_node] # def draft_callback(from_index): # from_node = manager.IndexToNode(from_index) # cargo_on_board = data["weight_demands"][from_node] # NON_CARGO_WEIGHT = 2500 # dwt = 4000 # comes from vessel description # immersion_summer = 200000 # comes from vessel description # draft = 100 # comes from vessel description # cargo_capacity = dwt - NON_CARGO_WEIGHT # cargo_capacity_unused = cargo_capacity - cargo_on_board # centimeter_reduction_in_draft = cargo_capacity_unused / immersion_summer # calculated_draft = draft - (0.01 * centimeter_reduction_in_draft) # return calculated_draft time_callbacks = [ make_time_callbacks(x) for x in range(data["num_vehicles"]) ] cost_callbacks = [ make_cost_callback(x) for x in range(data["num_vehicles"]) ] draft_callbacks = [ make_draft_callback(x) for x in range(data["num_vehicles"]) ] draft_callbacks_2 = [ make_draft_callback_2(x) for x in range(data["num_vehicles"]) ] transit_callback_indexes = [ routing.RegisterTransitCallback(cb) for cb in time_callbacks ] transit_callback_cost_indexes = [ routing.RegisterTransitCallback(cb) for cb in cost_callbacks ] transit_callback_draft_indexes = [ routing.RegisterTransitCallback(cb) for cb in draft_callbacks ] transit_callback_draft_2_indexes = [ routing.RegisterTransitCallback(cb) for cb in draft_callbacks_2 ] for ind, cb_index in enumerate(transit_callback_cost_indexes): routing.SetArcCostEvaluatorOfVehicle(cb_index, ind) time_for_vehicles = "time_for_vehicles" routing.AddDimensionWithVehicleTransits(transit_callback_indexes, 10, 10000, False, time_for_vehicles) cost_for_vehicles = "cost_for_vehicles" routing.AddDimensionWithVehicleTransits(transit_callback_cost_indexes, 0, 10000, False, cost_for_vehicles) time_dimension = routing.GetDimensionOrDie(time_for_vehicles) if "draft_demands" in data: draft_for_vehicles = "draft_for_vehicles" routing.AddDimensionWithVehicleTransits( transit_callback_draft_indexes, 0, 1000, # sets max draft any vessel can have True, draft_for_vehicles) draft_for_vehicles_2 = "draft_for_vehicles_2" routing.AddDimensionWithVehicleTransits( transit_callback_draft_2_indexes, 0, 1000, # sets max draft any vessel can have True, draft_for_vehicles_2) draft_dimension = routing.GetDimensionOrDie(draft_for_vehicles) draft_dimension_2 = routing.GetDimensionOrDie(draft_for_vehicles_2) # Add capacity restraints volume_demand_callback_index = routing.RegisterUnaryTransitCallback( volume_demand_callback) routing.AddDimensionWithVehicleCapacity( volume_demand_callback_index, 0, # null capacity slack data['vehicle_volume_capacities'], # vehicle maximum capacities True, # start cumul to zero "volume") weight_demand_callback_index = routing.RegisterUnaryTransitCallback( weight_demand_callback) routing.AddDimensionWithVehicleCapacity( weight_demand_callback_index, 0, # null capacity slack data['vehicle_weight_capacities'], # vehicle maximum capacities True, # start cumul to zero "weight") weight_dimension = routing.GetDimensionOrDie("weight") for pickups_deliveries, vehicle_for_cargo in zip( data['pickups_deliveries'], data["vehicle_for_cargo"]): pickup, dropoff = pickups_deliveries pickup = manager.NodeToIndex(pickup) dropoff = manager.NodeToIndex(dropoff) routing.AddPickupAndDelivery(pickup, dropoff) if vehicle_for_cargo is not None: routing.solver().Add( routing.VehicleVar(pickup) == vehicle_for_cargo) routing.solver().Add( routing.VehicleVar(pickup) == routing.VehicleVar(dropoff)) else: routing.solver().Add( routing.VehicleVar(pickup) == routing.VehicleVar(dropoff)) routing.solver().Add( time_dimension.CumulVar(pickup) <= time_dimension.CumulVar( dropoff)) if "draft_demands" in data: draft_dimension.CumulVar(pickup).SetMax( data["port_max_draft"][pickup]) draft_dimension_2.CumulVar(dropoff).SetMax( data["port_max_draft"][dropoff]) # add constraints on pickup and dropoff locations for pickup_dropoff, time_window, load_and_dropoff_times in zip( data["pickups_deliveries"], data["time_windows"], data["load_and_dropoff_times"]): pickup = pickup_dropoff[0] dropoff = pickup_dropoff[1] load_time = load_and_dropoff_times["load"] dropoff_time = load_and_dropoff_times["dropoff"] start_load, end_load = time_window["load_window"] start_dropoff, end_dropoff = time_window["dropoff_window"] # I think this does what it is supposed to do, but it is also slow # routing.solver().Add(time_dimension.CumulVar(pickup) >= (start_load + load_time)) # routing.solver().Add(time_dimension.CumulVar(pickup) < end_load) # routing.solver().Add(time_dimension.CumulVar(dropoff) >= start_dropoff) # routing.solver().Add(time_dimension.CumulVar( # dropoff) < (end_dropoff - dropoff_time)) time_dimension.CumulVar(pickup).SetRange(start_load + load_time, end_load) time_dimension.CumulVar(dropoff).SetRange( start_dropoff, end_dropoff - dropoff_time) # This allows for incomplete solutuon, for node in range(1, len(data['distance_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], 1000) # Just testing minStart and minEnd # It looks like it is working # vehicle_index = routing.Start(0) # time_dimension.CumulVar(vehicle_index).SetRange(0, 20) # routing.AddToAssignment(time_dimension.SlackVar(vehicle_index)) # end testing minStart and min End # for pv in data["port_to_allowed_vehicles"]: # index = manager.NodeToIndex(pv["port"]) # routing.VehicleVar(index).SetValues([-1] + pv["vehicles"]) # for ind, start_time in enumerate(data["vehicle_starting_time"]): # index = routing.Start(ind) # time_dimension.CumulVar(index).SetRange(start_time, start_time) # routing.AddToAssignment(time_dimension.SlackVar(index)) for i in range(data['num_vehicles']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) search_parameters = pywrapcp.DefaultRoutingSearchParameters() # PARALLEL_CHEAPEST_INSERTION is faster, but not finding the solution... search_parameters.first_solution_strategy = ( self.first_solution_strategy) # search_parameters.time_limit.seconds = 90 # we can set a limit, but it won't guarantee to find a solution! # if time expires before we find first solution # we get nothing back search_parameters.solution_limit = self.solution_limit search_parameters.local_search_metaheuristic = ( self.local_search_metaheuristic) # search_parameters.time_limit.seconds = None search_parameters.log_search = True assignment = routing.SolveWithParameters(search_parameters) if assignment: solution = get_solution(data, manager, routing, assignment) d_solution = dedummify(solution, data["dummy_to_ind"]) return {"solution": solution, "d_solution": d_solution} else: print("NO SOLUTION FOUND!!!") return None
def route_agents(self): """ Using vehicle routing algorithm to determine near-optimal agent assignments by minimizing the total build time. Inputs: Nothing Returns: assignments assignments :: list of dicts Each element is one assignment with keys 'agent' : the agent number 'location' : where they are 'arrive' : when they arrived 'link' : the portal to which they throw a link 'depart' : when they leave """ # # If num_agents is 1, then we have a trivial problem because # the order is already set # if self.num_agents == 1: assignments = [] for i in range(len(self.ordered_links)): if i == 0: arrive = 0 else: arrive = (depart + self.portals_dists[self.ordered_links[i - 1][0], self.ordered_links[i][0]] // _WALKSPEED) depart = arrive + _LINKTIME location = self.ordered_links[i][0] link = self.ordered_links[i][1] assignments.append({ 'agent': 0, 'location': location, 'arrive': arrive, 'link': link, 'depart': depart }) return assignments # # If the same origin appears multiple times sequentially, we # can remove the extras since the agent doesn't need to move. # Get that origin portal as well as the count of sequential # occurances # ordered_cut_origins, count_cut_origins = \ zip(*[(x, len(list(y))) for x, y in itertools.groupby(self.ordered_origins)]) # # Create origins_dists matrix, which has the distances between # each origin portal in the correct order. # origins_dists = np.array( [[self.portals_dists[o1][o2] for o1 in ordered_cut_origins] for o2 in ordered_cut_origins]) # # Optimize the agent routes. This is a vehicle routing # problem, with the constraint that each portal must be # visited in order. # # Since our agents can start and end at any portal, we add a # "dummy node" to the first row and column of origins_dists # that has a distance 0 to every other portal. Too, we cast # the distances between portals to an integer, which shouldn't # cause any problems since most (all?) portals are separated # by at least 1 meter. # origins_dists = np.hstack((np.zeros( (origins_dists.shape[0], 1)), origins_dists)) origins_dists = np.vstack( (np.zeros(origins_dists.shape[1]), origins_dists)) origins_dists = np.array(origins_dists, dtype=np.int) # # Create the routing index manager # Set starting and ending locations to index 0 for the dummy # depot # manager = pywrapcp.RoutingIndexManager(len(origins_dists), self.num_agents, 0) # # Create the routing model # routing = pywrapcp.RoutingModel(manager) # # Set the time callback # time_callback_index = routing.RegisterTransitCallback( functools.partial(time_callback(origins_dists, count_cut_origins), manager)) # # Set the cost function to minimize total time # routing.SetArcCostEvaluatorOfAllVehicles(time_callback_index) # # Add the total time as a dimension # 1000000 = can wait at each portal for a long time, # 1000000 = can take a long time to complete # False = do not start each agent at 0 time. # routing.AddDimension(time_callback_index, 1000000, 1000000, False, 'time') time_dimension = routing.GetDimensionOrDie('time') time_dimension.SetGlobalSpanCostCoefficient(100) # # Force order. If any of the links in the next group depend # on any of the links in this group, then the next group can't # be started until this one is finished. Otherwise, they can # be built at the same time. # for i in range(1, len(origins_dists) - 1): # N.B. node i corresponds to count_cut_origins[i-1] since # the later has no depot. this_index = manager.NodeToIndex(i) next_index = manager.NodeToIndex(i + 1) # # Get dependencies # this_link = int(np.sum(count_cut_origins[:i - 1])) this_size = count_cut_origins[i - 1] next_link = int(np.sum(count_cut_origins[:i])) next_size = count_cut_origins[i] for linki in range(this_link, this_link + this_size): for linkj in range(next_link, next_link + next_size): if ((self.ordered_links[linki] in self.ordered_links_depends[linkj]) or (self.ordered_links[linki][0] in self.ordered_links_depends[linkj])): # Dependency conflict break else: # No conflict yet continue # Dependency conflict break else: # No conflict, so they can be started simultaneously routing.solver().Add((time_dimension.CumulVar(next_index) >= time_dimension.CumulVar(this_index))) continue # is a conflict, so next has to be after this is finished # and communicated routing.solver().Add( (time_dimension.CumulVar(next_index) > (time_dimension.CumulVar(this_index) + count_cut_origins[i - 1] * _LINKTIME + _COMMTIME))) # # Start immediately, and we're trying to minimize total time. # for i in range(self.num_agents): time_dimension.CumulVar(routing.Start(i)).SetRange(0, 0) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # # Set search parameters, then close the model # search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = \ routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC search_parameters.local_search_metaheuristic = \ routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH search_parameters.solution_limit = self.max_route_solutions search_parameters.time_limit.seconds = self.max_route_runtime #search_parameters.log_search = True routing.CloseModelWithParameters(search_parameters) # # A naive initial solution is that agents alternate portals # naive_route = [ list(range(1, len(origins_dists)))[i::self.num_agents] for i in range(self.num_agents) ] naive_solution = \ routing.ReadAssignmentFromRoutes(naive_route, True) # # Solve with initial solution # solution = routing.SolveFromAssignmentWithParameters( naive_solution, search_parameters) if not solution: raise ValueError("No valid assignments found") # # Package results # assignments = [] for agent in range(self.num_agents): # # Loop over all assignments, except first (dummy depot) # index = routing.Start(agent) index = solution.Value(routing.NextVar(index)) while not routing.IsEnd(index): node = manager.IndexToNode(index) # # Get time agent arrives at this node # arrive = solution.Min(time_dimension.CumulVar(index)) # # Node is index in origins_dists, which corresponds # to index-1 in ordered_cut_origins since # ordered_cut_origins doesn't have depot. This is # related to the index in ordered_links via # linki = int(np.sum(count_cut_origins[:node - 1])) # # Loop over all links starting now at this origin # for i in range(linki, linki + count_cut_origins[node - 1]): # # add link time. Final link at this origin # includes communication time # location = self.ordered_links[i][0] link = self.ordered_links[i][1] depart = arrive + _LINKTIME assignments.append({ 'agent': agent, 'location': location, 'arrive': arrive, 'link': link, 'depart': depart }) arrive = depart # # Get next index and move on # index = solution.Value(routing.NextVar(index)) # # Sort assignments by arrival time # assignments = sorted(assignments, key=lambda k: k['arrive']) return assignments
def optimize(inst, capacity): def create_data_model(inst, capacity): data = {} data['distance_matrix'] = inst.distances data['demands'] = inst.demands data['vehicle_capacities'] = [capacity] * inst.size data['num_vehicles'] = sum(inst.demands) data['depot'] = 0 return data def get_routes(solution, routing, manager): """Get vehicle routes from a solution and store them in an array.""" # Get vehicle routes and store them in a two dimensional array whose # i,j entry is the jth location visited by vehicle i along its route. routes = [] for route_nbr in range(routing.vehicles()): index = routing.Start(route_nbr) route = [manager.IndexToNode(index)] while not routing.IsEnd(index): index = solution.Value(routing.NextVar(index)) route.append(manager.IndexToNode(index)) routes.append(route) return routes 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] 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] # --- RUN PROGRAM --- # Zero cost if no demands if all(dem == 0 for dem in inst.demands): return [[]] # Set up data model data = create_data_model(inst, capacity) # Create the routing index manager manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # Create routing model routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback transit_callback_index = routing.RegisterTransitCallback(distance_callback) # Define cost of each arc routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add capacity constraint 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') # Setting first solution heuristic search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # Solve the problem solution = routing.SolveWithParameters(search_parameters) all_routes = get_routes(solution, routing, manager) nonempty_routes = [route for route in all_routes if not all(i == 0 for i in route)] # Remove the depot from the optimal routes parsed_routes = [route[1:-1] for route in nonempty_routes] return parsed_routes
def main(): """Entry point of the program.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Define cost of each arc. # [START arc_cost] def distance_callback(from_index, to_index): """Returns the manhattan 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) routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # [START distance_constraint] dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 3000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # [END distance_constraint] # Define Transportation Requests. # [START pickup_delivery_constraint] for request in data['pickups_deliveries']: pickup_index = manager.NodeToIndex(request[0]) delivery_index = manager.NodeToIndex(request[1]) routing.AddPickupAndDelivery(pickup_index, delivery_index) routing.solver().Add( routing.VehicleVar(pickup_index) == routing.VehicleVar( delivery_index)) routing.solver().Add( distance_dimension.CumulVar(pickup_index) <= distance_dimension.CumulVar(delivery_index)) routing.SetPickupAndDeliveryPolicyOfAllVehicles( pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_LIFO) # [END pickup_delivery_constraint] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION) # [END parameters] # Solve the problem. # [START solve] assignment = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if assignment: print_solution(data, manager, routing, assignment)
def main(input, time=None, solution_limit=None, lns_time=None, penalty=None, log_search=bool, first_solution_method=None, second_solution_method=None): """Entry point of the program.""" # Instantiate the data problem. data = create_data_madel(input) # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) add_distance_callback(routing, manager, data) if penalty != None: for node in range(1, len(data['distance_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], penalty) search_parameters = pywrapcp.DefaultRoutingSearchParameters() if solution_limit != None: search_parameters.solution_limit = solution_limit if time != None: search_parameters.time_limit.seconds = time if lns_time != None: search_parameters.lns_time_limit.seconds = lns_time # Setting first solution heuristic. if first_solution_method == 'PATH_CHEAPEST_ARC': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) elif first_solution_method == 'SAVINGS': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.SAVINGS) elif first_solution_method == 'SWEEP': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.SWEEP) elif first_solution_method == 'CHRISTOFIDES': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.CHRISTOFIDES) elif first_solution_method == 'BEST_INSERTION': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.BEST_INSERTION) elif first_solution_method == 'PARALLEL_CHEAPEST_INSERTION': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION ) elif first_solution_method == 'FIRST_UNBOUND_MIN_VALUE': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.FIRST_UNBOUND_MIN_VALUE) elif first_solution_method == 'LOCAL_CHEAPEST_ARC': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.LOCAL_CHEAPEST_ARC) elif first_solution_method == 'GLOBAL_CHEAPEST_ARC': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.GLOBAL_CHEAPEST_ARC) elif first_solution_method == 'AUTOMATIC': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.AUTOMATIC) elif first_solution_method == 'LOCAL_CHEAPEST_INSERTION': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.LOCAL_CHEAPEST_INSERTION) elif first_solution_method == 'ALL_UNPERFORMED': search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.ALL_UNPERFORMED) elif first_solution_method == 'GREEDY_DESCENT': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GREEDY_DESCENT) if second_solution_method == 'TABU_SEARCH': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.TABU_SEARCH) elif second_solution_method == 'GUIDED_LOCAL_SEARCH': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) elif second_solution_method == 'SIMULATED_ANNEALING': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.SIMULATED_ANNEALING) elif second_solution_method == 'OBJECTIVE_TABU_SEARCH': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.OBJECTIVE_TABU_SEARCH) elif second_solution_method == 'GREEDY_DESCENT': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GREEDY_DESCENT) elif second_solution_method == 'AUTOMATIC': search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.AUTOMATIC) if log_search == True: search_parameters.log_search = True # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. routes = get_routes(data, solution, routing, manager) if solution: return routes
def dispatch_jobs_1_cluster(self): cluster_begin_time = datetime.now() # Create and register a transit callback. def distance_callback(from_index, to_index): # Convert from routing variable Index to distance matrix NodeIndex. from_node = manager.IndexToNode(from_index) # - 1 to_node = manager.IndexToNode(to_index) # - 1 if from_node == to_node: return 0 return self._get_travel_time_2locations( self.cluster_list[from_node][1:3], self.cluster_list[to_node][1:3]) self.distance_callback_func = distance_callback # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(self.cluster_list), 1, 0) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) transit_callback_index = routing.RegisterTransitCallback( distance_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Distance constraint. dimension_name = "Distance" routing.AddDimension( transit_callback_index, 0, # no slack 900, # vehicle maximum travel distance True, # start cumul to zero dimension_name, ) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) search_parameters.log_search = True search_parameters.time_limit.seconds = self.config["max_exec_seconds"] # Solve the problem. solution = routing.SolveWithParameters(search_parameters) cluster_total_time = datetime.now() - cluster_begin_time print( f"Algorithm Done. nbr workers: {len(self.worker_slots)}, nbr jobs: {len(self.cluster_list)}, Elapsed: {cluster_total_time}" ) # Print solution on console. if solution: self.print_solution(manager, routing, solution) self.save_solution(manager, routing, solution) else: print(f"Failed on cluster")
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. # [START data] num_locations = 20 num_vehicles = 5 depot = 0 # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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 1 transit_callback_index = routing.RegisterTransitCallback(distance_callback) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # [START distance_constraint] dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 3000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # [END distance_constraint] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) search_parameters.log_search = True search_parameters.time_limit.FromSeconds(10) # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print_solution(manager, routing, solution)
def routeMultiVehicle(self): ''' Returns: ''' """Entry point of the program.""" # Instantiate the data problem. data = self.create_data_model() # Create the routing index manager. 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 Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 999999999999, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(self._span_cost_coeff) # 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') # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) if solution: ordered_indices = self.get_formatted_output( manager, routing, solution) route_solution_nonformatted = [] ordered_coords = [] route_solution = [] for i in range(len(ordered_indices)): rsn_row = [] oc_row = [] for j in ordered_indices[i]: rsn_row.append(self._addresses[j]) oc_row.append(self._coordinates[j]) route_solution_nonformatted.append(rsn_row) ordered_coords.append(oc_row) route_solution.append( basicrouter.maputil.getmappedaddresses( rsn_row, self._apikey)) self.output = (route_solution_nonformatted, ordered_coords, ordered_indices, route_solution) return self.output else: raise Exception('No solution is found.')
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], # data['depot'], data['starts'], data['ends'] ) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # dimension_name = 'Distance' # routing.AddDimension( # transit_callback_index, # 0, # no slack # 3000, # vehicle maximum travel distance # True, # start cumul to zero # dimension_name) # distance_dimension = routing.GetDimensionOrDie(dimension_name) # distance_dimension.SetGlobalSpanCostCoefficient(100) # Add Capacity constraint. # [START 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') # [END capacity_constraint] # Add Time Window constraint time_evaluator_index = routing.RegisterTransitCallback( partial(create_time_evaluator(data), manager)) add_time_window_constraints(routing, manager, data, time_evaluator_index) # penalty = 20000 # for node in range(0, len(data['distance_matrix'])): # if manager.NodeToIndex(node) == -1: # continue # routing.AddDisjunction([manager.NodeToIndex(node)], penalty) # Setting first solution heuristic. # [START parameters] # Setting first solution heuristic (cheapest addition). search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-membe # [END parameters] # Solve the problem. # [START solve] assignment = routing.SolveWithParameters(search_parameters) # [END solve] data['previous_solution'] = assignment # Print solution on console. # [START print_solution] if assignment: print_solution(data, manager, routing, assignment)
routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # configure speedy clients for idx in data['speedy_idx']: index = manager.NodeToIndex(idx) capacity_dimension.SlackVar(index).SetValue(0) for vehicle_index in range(len(data['ends'])): end_index = routing.End(i) routing.solver().Add( capacity_dimension.CumulVar(end_index) <= capacity_dimension.CumulVar(index) + 3) #""" nodes = [] for i in range(cars_start): nodes.append(routing.AddDisjunction([manager.NodeToIndex(i)],2147483647999)) search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION) #search_parameters.time_limit.seconds = 4 routing.SetArcCostEvaluatorOfAllVehicles(time_callback_index) assignment = routing.SolveWithParameters(search_parameters) if assignment: print_solution(manager,routing,assignment,data) else: print('no solution') #with open('data.json', 'w', encoding='utf-8') as f: # json.dump(data, f, ensure_ascii=False, indent=4)
def main(): # pylint: disable=too-many-locals,too-many-branches """Entry point of the program.""" parser = argparse.ArgumentParser(description='Output VRP as svg image.') parser.add_argument('-tsp', '--tsp', action='store_true', help='use 1 vehicle') parser.add_argument('-vrp', '--vrp', action='store_true', help='use 4 vehicle') parser.add_argument('-gs', '--global-span', action='store_true', help='use global span constraints') parser.add_argument('-c', '--capacity', action='store_true', help='use capacity constraints') parser.add_argument('-r', '--resources', action='store_true', help='use resources constraints') parser.add_argument('-dn', '--drop-nodes', action='store_true', help='allow drop nodes (disjuntion constraints)') parser.add_argument('-tw', '--time-windows', action='store_true', help='use time-window constraints') parser.add_argument('-se', '--starts-ends', action='store_true', help='use multiple starts & ends') parser.add_argument('-pd', '--pickup-delivery', action='store_true', help='use pickup & delivery constraints') parser.add_argument('-fifo', '--fifo', action='store_true', help='use pickup & delivery FIFO Policy') parser.add_argument('-lifo', '--lifo', action='store_true', help='use pickup & delivery LIFO Policy') parser.add_argument('-s', '--solution', action='store_true', help='print solution') args = vars(parser.parse_args()) # Instantiate the data problem. # [START data] data = DataModel(args) # [END data] if not args['solution']: # Print svg on cout printer = SVGPrinter(args, data) printer.print_to_console() return 0 # Create the routing index manager. # [START index_manager] if args['starts_ends']: manager = pywrapcp.RoutingIndexManager(len(data.locations), data.num_vehicles, data.starts, data.ends) else: manager = pywrapcp.RoutingIndexManager(len(data.locations), data.num_vehicles, data.depot) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Register distance callback def distance_callback(from_index, to_index): """Returns the manhattan 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] distance_callback_index = routing.RegisterTransitCallback( distance_callback) # Register time callback def time_callback(from_index, to_index): """Returns the manhattan distance travel time 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.time_matrix[from_node][to_node] time_callback_index = routing.RegisterTransitCallback(time_callback) # Register demands callback 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) if args['time_windows'] or args['resources']: routing.SetArcCostEvaluatorOfAllVehicles(time_callback_index) else: routing.SetArcCostEvaluatorOfAllVehicles(distance_callback_index) if args['global_span'] or args['pickup_delivery']: dimension_name = 'Distance' routing.AddDimension(distance_callback_index, 0, 3000, True, dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) if args['capacity'] or args['drop_nodes']: routing.AddDimensionWithVehicleCapacity(demand_callback_index, 0, data.vehicle_capacities, True, 'Capacity') if args['drop_nodes']: # Allow to drop nodes. penalty = 1000 for node in range(1, len(data.locations)): routing.AddDisjunction([manager.NodeToIndex(node)], penalty) if args['pickup_delivery']: dimension_name = 'Distance' routing.AddDimension(distance_callback_index, 0, 3000, True, dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) for request in data.pickups_deliveries: pickup_index = manager.NodeToIndex(request[0]) delivery_index = manager.NodeToIndex(request[1]) routing.AddPickupAndDelivery(pickup_index, delivery_index) routing.solver().Add( routing.VehicleVar(pickup_index) == routing.VehicleVar( delivery_index)) routing.solver().Add( distance_dimension.CumulVar(pickup_index) <= distance_dimension.CumulVar(delivery_index)) if args['fifo']: routing.SetPickupAndDeliveryPolicyOfAllVehicles( pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_FIFO) if args['lifo']: routing.SetPickupAndDeliveryPolicyOfAllVehicles( pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_LIFO) if args['starts_ends']: dimension_name = 'Distance' routing.AddDimension(distance_callback_index, 0, 2000, True, dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) time = 'Time' if args['time_windows'] or args['resources']: routing.AddDimension(time_callback_index, 30, 30, False, time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot and 'copy' the # slack var in the solution object (aka Assignment) to print it. for location_idx, time_window in enumerate(data.time_windows): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) routing.AddToAssignment(time_dimension.SlackVar(index)) # Add time window constraints for each vehicle start node and 'copy' the # slack var in the solution object (aka Assignment) to print it. for vehicle_id in range(data.num_vehicles): index = routing.Start(vehicle_id) time_window = data.time_windows[0] time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) routing.AddToAssignment(time_dimension.SlackVar(index)) # Instantiate route start and end times to produce feasible times. for vehicle_id in range(data.num_vehicles): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(vehicle_id))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(vehicle_id))) if args['resources']: # Add resource constraints at the depot. time_dimension = routing.GetDimensionOrDie(time) solver = routing.solver() intervals = [] for i in range(data.num_vehicles): # Add loading time at start of routes intervals.append( solver.FixedDurationIntervalVar( time_dimension.CumulVar(routing.Start(i)), data.vehicle_load_time, 'depot_interval')) # Add unloading time at end of routes. intervals.append( solver.FixedDurationIntervalVar( time_dimension.CumulVar(routing.End(i)), data.vehicle_unload_time, 'depot_interval ')) depot_usage = [1 for i in range(data.num_vehicles * 2)] solver.AddConstraint( solver.Cumulative(intervals, depot_usage, data.depot_capacity, 'depot')) # Setting first solution heuristic (cheapest addition). search_parameters = pywrapcp.DefaultRoutingSearchParameters() # pylint: disable=no-member if not args['pickup_delivery']: search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) else: search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION ) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) search_parameters.time_limit.FromSeconds(2) # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) # Print the solution. printer = SVGPrinter(args, data, manager, routing, assignment) printer.print_to_console() return 0
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. data = create_data_model() time_matrix = compute_euclidean_distance_matrix(data['locations']) # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['time_windows']), data['num_vehicles'], data['depot']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) # Create and register a transit callback. def time_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 time_matrix[from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Time Windows constraint. time = 'Time' routing.AddDimension( transit_callback_index, 10, # allow waiting time 100, # maximum time per vehicle False, # Don't force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][1][1]) # Add time window constraints for each vehicle start node. for vehicle_id in range(data['num_vehicles']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) # Instantiate route start and end times to produce feasible times. for i in range(data['num_vehicles']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # 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 False, # start cumul to zero 'Capacity') # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.TABU_SEARCH) search_parameters.time_limit.FromSeconds(1) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. if solution: solution_dict = print_solution(data, manager, routing, solution) coordinates = [ (35, 35), (41, 49), (35, 17), (55, 45), (55, 20), (15, 30), (25, 30), (20, 50), (10, 43), (55, 60), (30, 60), (20, 65), (50, 35), (30, 25), (15, 10), (30, 5), (10, 20), (5, 30), (20, 40), (15, 60), (45, 65), (45, 20), (45, 10), (55, 5), #23 (65, 35), (65, 20), (45, 30), (35, 40), (41, 37), (64, 42), (40, 60), (31, 52), (35, 69), (53, 52), (65, 55), (63, 65), (2, 60), (20, 20), (5, 5), (60, 12), (40, 25), (42, 7), (24, 12), (23, 3), #43 (11, 14), (6, 38), (2, 48), (8, 56), (13, 52), (6, 68), (47, 47), (49, 58), (27, 43), (37, 31), (57, 29), (63, 23), (53, 12), (32, 12), (36, 26), (21, 24), (17, 34), (12, 24), (24, 58), (27, 69), (15, 77), (62, 77), (49, 73), (67, 5), (56, 39), (37, 47), (37, 56), (57, 68), #71 (47, 16), (44, 17), (46, 13), (49, 11), (49, 42), (53, 43), (61, 52), (57, 48), (56, 37), (55, 54), (15, 47), (14, 37), (11, 31), (16, 22), (4, 18), (28, 18), (26, 52), (26, 35), (31, 67), (15, 19), (22, 22), (18, 24), (26, 27), (25, 24), (22, 27), (25, 21), (19, 21), (20, 26), (18, 18), #100 ] X = np.array([x[0] for x in coordinates]) Y = np.array([x[1] for x in coordinates]) f, ax = plt.subplots(figsize=[8, 6]) ax.plot(X, Y, 'ko', markersize=8) ax.plot(X[0], Y[0], 'gX', markersize=30) for i, txt in enumerate(coordinates): ax.text(X[i], Y[i], f"{i}") vehicle_colors = [ "g", "k", "r", "m", "c", "b", "y", "g", "k", "r", "m", "c", "b", "y", "g", "k", "r", "m", "c", "b", "y", "g", "k", "r", "m" ] #warna garis for vehicle in solution_dict: ax.plot(X[solution_dict[vehicle] + [0]], Y[solution_dict[vehicle] + [0]], f'{vehicle_colors[vehicle]}--') ax.set_title("Tabu search - Parallel cheapest insertion") plt.show()
def solve_CVRPTW_PD(data, solverParams: SolverParameters, priorities) -> [pywrapcp.RoutingIndexManager, pywrapcp.RoutingModel, pywrapcp.Assignment]: # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot']) # 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['time_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(distance_callback) # Define cost of each arc. routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # Add Time Windows constraint. time = 'Time' routing.AddDimension( transit_callback_index, 30000, # allow waiting time 3000, # maximum time per vehicle False, # Don't force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) # Add time window constraints for each vehicle start node. for vehicle_id in range(data['num_vehicles']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) # 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') # Allow to drop nodes. #penalty = solverParams.unServedDemandPenalty for node in range(1, len(data['time_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], priorities[node-1]) #Add Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 100, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # Define Transportation Requests. for request in data['pickups_deliveries']: pickup_index = manager.NodeToIndex(request[0]) delivery_index = manager.NodeToIndex(request[1]) routing.AddPickupAndDelivery(pickup_index, delivery_index) routing.solver().Add( routing.VehicleVar(pickup_index) == routing.VehicleVar( delivery_index)) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) search_parameters.time_limit.FromSeconds(solverParams.maxTimeLimitSecs) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) return [manager, routing, solution]
def main(): """Solve the VRP with time windows.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START transit_callback] def time_callback(from_index, to_index): """Returns the travel time between the two nodes.""" # Convert from routing variable Index to time matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data['time_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Time Windows constraint. # [START time_windows_constraint] time = 'Time' routing.AddDimension( transit_callback_index, 30, # allow waiting time 30, # maximum time per vehicle False, # Don't force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot. for location_idx, time_window in enumerate(data['time_windows']): if location_idx == data['depot']: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) # Add time window constraints for each vehicle start node. depot_idx = data['depot'] for vehicle_id in range(data['num_vehicles']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange( data['time_windows'][depot_idx][0], data['time_windows'][depot_idx][1]) # [END time_windows_constraint] # Instantiate route start and end times to produce feasible times. # [START depot_start_end_times] for i in range(data['num_vehicles']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # [END depot_start_end_times] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print_solution(data, manager, routing, solution)
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # [START distance_constraint] dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 3_000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # [END distance_constraint] routing.AddConstantDimensionWithSlack( 0, # transit 0 42 * 16, # capacity: be able to store PEAK*ROUTE_LENGTH in worst case 42, # slack_max: to be able to store peak in slack True, # Fix StartCumulToZero not really matter here 'One') dim_one = routing.GetDimensionOrDie('One') routing.AddConstantDimensionWithSlack( 0, # transit 0 42 * 16, # capacity: be able to have PEAK value in CumulVar(End) 42, # slack_max: to be able to store peak in slack True, # Fix StartCumulToZero YES here 'Two') dim_two = routing.GetDimensionOrDie('Two') # force depot Slack to be cost since we don't have any predecessor... for v in range(manager.GetNumberOfVehicles()): start = routing.Start(v) dim_one.SlackVar(start).SetValue(data['cost'][0]) routing.AddToAssignment(dim_one.SlackVar(start)) dim_two.SlackVar(start).SetValue(data['cost'][0]) routing.AddToAssignment(dim_two.SlackVar(start)) # Step by step relation # Slack(N) = max( Slack(N-1) , cost(N) ) solver = routing.solver() for node in range(1, 17): index = manager.NodeToIndex(node) routing.AddToAssignment(dim_one.SlackVar(index)) routing.AddToAssignment(dim_two.SlackVar(index)) test = [] for v in range(manager.GetNumberOfVehicles()): previous_index = routing.Start(v) cond = routing.NextVar(previous_index) == index value = solver.Max(dim_one.SlackVar(previous_index), data['cost'][node]) test.append(cond * value) for previous in range(1, 17): previous_index = manager.NodeToIndex(previous) cond = routing.NextVar(previous_index) == index value = solver.Max(dim_one.SlackVar(previous_index), data['cost'][node]) test.append(cond * value) solver.Add(solver.Sum(test) == dim_one.SlackVar(index)) # relation between dimensions, copy last node Slack from dim ONE to dim TWO for node in range(1, 17): index = manager.NodeToIndex(node) values = [] for v in range(manager.GetNumberOfVehicles()): next_index = routing.End(v) cond = routing.NextVar(index) == next_index value = dim_one.SlackVar(index) values.append(cond * value) solver.Add(solver.Sum(values) == dim_two.SlackVar(index)) # Should force all others dim_two slack var to zero... for v in range(manager.GetNumberOfVehicles()): end = routing.End(v) dim_two.SetCumulVarSoftUpperBound(end, 0, 1000) # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) # search_parameters.log_search = True search_parameters.time_limit.FromSeconds(5) # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print_solution(data, manager, routing, solution) else: print('No solution found !')
def solve_with_ortools(input_data): # def solve_it(input_data): """Simple travelling salesman problem between cities.""" """Stores the data for the problem.""" lines = input_data.split('\n') nodeCount = int(lines[0]) points = [] for i in range(1, nodeCount+1): line = lines[i] parts = line.split() points.append(Point(float(parts[0]), float(parts[1]))) data = {} data['distance_matrix'] = build_distance_matrix_from_input(points) # [ # [0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972], # [2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579], # [713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260], # [1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987], # [1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371], # [1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999], # [2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701], # [213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099], # [2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600], # [875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162], # [1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200], # [2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504], # [1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0], # ] # yapf: disable data['num_vehicles'] = 1 data['depot'] = 0 # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # Create Routing Model. routing = pywrapcp.RoutingModel(manager) 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) # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. # if solution: # print_solution(manager, routing, solution) # print(solution) value = 0 index = routing.Start(0) while not routing.IsEnd(index): newindex = solution.Value(routing.NextVar(index)) value += length(points[manager.IndexToNode(index)],points[manager.IndexToNode(newindex)]) index = newindex # print("value",value) # output_data = '%.2f' % solution.ObjectiveValue() + ' ' + str(0) + '\n' output_data = '%.2f' % value + ' ' + str(0) + '\n' index = routing.Start(0) route_distance = 0 while not routing.IsEnd(index): sol = manager.IndexToNode(index) output_data += " " + str(sol) index = solution.Value(routing.NextVar(index)) # output_data += ' '.join(map(str, solution)) return output_data
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. mode = int( input( "press 1 to run with default values, 2 to run with custom values \n enter your choice: " )) if (mode == 1): bus_cap = 32 max_dist_veh = 100 print( "Running with default values.\nbus capacity = 32, max vehicle distance = 100km" ) if (mode == 2): bus_cap = int(input("Enter the capacity of each bus: ")) max_dist_veh = int( input("enter the max vehicle distance a vehicle can travel: ")) else: bus_cap = 32 max_dist_veh = 100 print( "incorrect option choosed, running with default values.\nbus capacity = 32, max vehicle distance = 100km" ) data = create_data_model(bus_cap) # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # 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 Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack max_dist_veh * 1000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(0) search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) search_parameters.time_limit.seconds = 10 search_parameters.log_search = True # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) # assignment = routing2.SolveFromAssignmentWithParameters(assignment, search_parameters) # Print solution on console. if assignment: print_solution(data, manager, routing, assignment) else: print('NO SOLUTION')
def main(): """Solve the CVRP problem.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Capacity constraint. # [START 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') # Allow to drop nodes. penalty = 1000 for node in range(1, len(data['distance_matrix'])): routing.AddDisjunction([manager.NodeToIndex(node)], penalty) # [END capacity_constraint] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # [END parameters] # Solve the problem. # [START solve] assignment = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if assignment: print_solution(data, manager, routing, assignment)
def solvemulti_nodistlim(data): """Solve the CVRP problem.""" # Create the routing index manager. 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 Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack #set to data['penalty'] since we do not want there to be an effective distance constraint data['penalty'], # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) #uncomment the below line to make the solver prioritize minimizing the maximum distance of any vehicle (we usually want to prioritize # nodes visited) #we want the max path length of any vehicle to be minimized in mapping applications where we must visit every node, #and assuming infinite battery swaps. distance_dimension.SetGlobalSpanCostCoefficient(100) #do NOT allow drops --> there should be no situation in which nodes are dropped. """ penalty = data['penalty'] 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.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_MOST_CONSTRAINED_ARC) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.SAVINGS) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.SWEEP) search_parameters.time_limit.seconds = 20 search_parameters.solution_limit = 200 # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. if solution: return manager, routing, solution else: return None, None, None
def main(): """Entry point of the program.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['starts'], data['ends']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START 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) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Distance constraint. # [START distance_constraint] dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack 2000, # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) distance_dimension.SetGlobalSpanCostCoefficient(100) # [END distance_constraint] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print_solution(data, manager, routing, solution)
def solveconnecteddepots(data): """Solve the CVRP problem.""" # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), data['num_vehicles'], data['depot']) # 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 Distance constraint. dimension_name = 'Distance' routing.AddDimension( transit_callback_index, 0, # no slack #set to data['max_distance'] if restricting distance of vehicle data['max_distance'], # vehicle maximum travel distance True, # start cumul to zero dimension_name) distance_dimension = routing.GetDimensionOrDie(dimension_name) #uncomment the below line to make the solver prioritize minimizing the maximum distance of any vehicle (we usually want to prioritize # nodes visited) #distance_dimension.SetGlobalSpanCostCoefficient(100) #allow drops --> penalty of dropping a node should be high EXCEPT FOR DEPOTS penalty = data['penalty'] for node in range(data['num_depots'], 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.time_limit.seconds = 45 search_parameters = pywrapcp.DefaultRoutingSearchParameters() #search_parameters.local_search_metaheuristic = (routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.PATH_MOST_CONSTRAINED_ARC) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.SAVINGS) #search_parameters.first_solution_strategy = (routing_enums_pb2.FirstSolutionStrategy.SWEEP) search_parameters.time_limit.seconds = 10 #search_parameters.solution_limit = 200 # Solve the problem. solution = routing.SolveWithParameters(search_parameters) # Print solution on console. if solution: return manager, routing, solution else: return None, None, None
def main(): """Solve the VRP with time windows.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START transit_callback] def time_callback(from_index, to_index): """Returns the travel time + service time between the two nodes.""" # Convert from routing variable Index to time matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data['time_matrix'][from_node][to_node] + data['service_time'][ from_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Time Windows constraint. time = 'Time' routing.AddDimension( transit_callback_index, 10, # needed optional waiting time to place break 180, # maximum time per vehicle True, # Force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) time_dimension.SetGlobalSpanCostCoefficient(10) # Breaks # [START break_constraint] # warning: Need a pre-travel array using the solver's index order. node_visit_transit = [0] * routing.Size() for index in range(routing.Size()): node = manager.IndexToNode(index) node_visit_transit[index] = data['service_time'][node] break_intervals = {} for v in range(data['num_vehicles']): break_intervals[v] = [ routing.solver().FixedDurationIntervalVar( 50, # start min 60, # start max 10, # duration: 10 min False, # optional: no f'Break for vehicle {v}') ] time_dimension.SetBreakIntervalsOfVehicle( break_intervals[v], # breaks v, # vehicle index node_visit_transit) # [END break_constraint] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) search_parameters.local_search_metaheuristic = ( routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) #search_parameters.log_search = True search_parameters.time_limit.FromSeconds(2) # [END parameters] # Solve the problem. # [START solve] solution = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if solution: print_solution(manager, routing, solution) else: print('No solution found !')
def generate_planning(timeout, verbose, calculate_distance, engineers=None, car_locations=None, work_items=None, availabilities=None): """ The main planning function. This function does the following: - Create a datamodel for the routing manager to reference. - Create a routing manager. - Add constraints based on business rules. - Calculate an optimal solution withing a given timeframe. - Log the solution. - Returns a list of engineers and workitems. :return: """ print("Timeout set to", timeout) print('Creating datamodel') data_model = create_data_model(engineers, car_locations, work_items, availabilities) print('Creating manager') manager = pywrapcp.RoutingIndexManager(data_model.number_of_nodes, data_model.number_of_engineers, data_model.start_positions, data_model.end_positions) routing = pywrapcp.RoutingModel(manager) print('Applying constraints') routing = DistanceConstraint().apply(manager, routing, data_model) routing = CapacityConstraint().apply(manager, routing, data_model) routing = PenaltyConstraint().apply(manager, routing, data_model) routing = IsAllowedToVisitConstraint().apply(manager, routing, data_model) search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.local_search_metaheuristic = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH search_parameters.time_limit.seconds = timeout datetime.now().strftime("%H:%M:%S") print("date and time: ", datetime.now().strftime("%H:%M:%S")) def record_solution(): print("date and time: ", datetime.now().strftime("%H:%M:%S")) print(routing.CostVar().Max()) routing.AddAtSolutionCallback(record_solution) print('Calculating solutions') for i in range(0, 3): solution = routing.SolveWithParameters(search_parameters) # solution = routing.SolveFromAssignmentWithParameters( # initial_solution, search_parameters) print(solution.ObjectiveValue()) print('Solution calculated') if solution: print('Processing solution') planning = process_solution(data_model, manager, routing, solution, calculate_distance) if data_model.verify_planning(planning, solution): break else: print('No solution found') return [], [engineer['id'] for engineer in data_model.engineers], \ [work_item['id'] for work_item in data_model.work_items], {} return data_model.best_planning
def main(): """Solve the VRP with time windows.""" # Instantiate the data problem. # [START data] data = create_data_model() # [END data] # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot']) # [END index_manager] # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) # [END routing_model] # Create and register a transit callback. # [START transit_callback] def time_callback(from_index, to_index): """Returns the travel time between the two nodes.""" # Convert from routing variable Index to time matrix NodeIndex. from_node = manager.IndexToNode(from_index) to_node = manager.IndexToNode(to_index) return data['time_matrix'][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # [END transit_callback] # Define cost of each arc. # [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index) # [END arc_cost] # Add Time Windows constraint. # [START time_windows_constraint] time = 'Time' routing.AddDimension( transit_callback_index, 60, # allow waiting time 60, # maximum time per vehicle False, # Don't force start cumul to zero. time) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot # and 'copy' the slack var in the solution object (aka Assignment) to print it for location_idx, time_window in enumerate(data['time_windows']): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1]) routing.AddToAssignment(time_dimension.SlackVar(index)) # Add time window constraints for each vehicle start node # and 'copy' the slack var in the solution object (aka Assignment) to print it for vehicle_id in range(data['num_vehicles']): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0], data['time_windows'][0][1]) routing.AddToAssignment(time_dimension.SlackVar(index)) # [END time_windows_constraint] # Add resource constraints at the depot. # [START depot_load_time] solver = routing.solver() intervals = [] for i in range(data['num_vehicles']): # Add time windows at start of routes intervals.append( solver.FixedDurationIntervalVar( time_dimension.CumulVar(routing.Start(i)), data['vehicle_load_time'], 'depot_interval')) # Add time windows at end of routes. intervals.append( solver.FixedDurationIntervalVar( time_dimension.CumulVar(routing.End(i)), data['vehicle_unload_time'], 'depot_interval')) # [END depot_load_time] # [START depot_capacity] depot_usage = [1 for i in range(len(intervals))] solver.AddConstraint( solver.Cumulative(intervals, depot_usage, data['depot_capacity'], 'depot')) # [END depot_capacity] # Instantiate route start and end times to produce feasible times. # [START depot_start_end_times] for i in range(data['num_vehicles']): routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.Start(i))) routing.AddVariableMinimizedByFinalizer( time_dimension.CumulVar(routing.End(i))) # [END depot_start_end_times] # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # [END parameters] # Solve the problem. # [START solve] assignment = routing.SolveWithParameters(search_parameters) # [END solve] # Print solution on console. # [START print_solution] if assignment: print_solution(data, manager, routing, assignment) # [END print_solution] else: print('No solution found !')
def solve_it(input_data): # Modify this code to run your optimization algorithm # parse the input lines = input_data.split('\n') parts = lines[0].split() customer_count = int(parts[0]) vehicle_count = int(parts[1]) vehicle_capacity = int(parts[2]) customers = [] for i in range(1, customer_count + 1): line = lines[i] parts = line.split() customers.append( Customer(i - 1, int(parts[0]), float(parts[1]), float(parts[2]))) #the depot is always the first customer in the input depot = customers[0] vehicle_tours = [] outputData = "" print("nodes: %s" % customer_count) useGoogleVRPSolver = True timeLimit = 60 solutionStrategy = routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC localSearchStrategy = routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH if customer_count == 200: #problem 5 useGoogleVRPSolver = False #timeLimit = 18000 #solutionStrategy = routing_enums_pb2.FirstSolutionStrategy.GLOBAL_CHEAPEST_ARC #localSearchStrategy = routing_enums_pb2.LocalSearchMetaheuristic.TABU_SEARCH elif customer_count == 101: #problem 4 timeLimit = 1800 elif customer_count == 421: #problem 6 timeLimit = 1800 if useGoogleVRPSolver == True: # Create the routing index manager. manager = pywrapcp.RoutingIndexManager(len(customers), vehicle_count, depot.index) # 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) #absLength = int(length(customers[from_node], customers[to_node])*100) #print("from: %s to %s = " %(from_node, to_node), end="") #print(absLength) return length(customers[from_node], customers[to_node]) * 100 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] #print("customer %s = " %from_node, end="") #print(customers[from_node].demand) return customers[from_node].demand vehicleCap = [vehicle_capacity for i in range(vehicle_count)] #print(vehicleCap) demand_callback_index = routing.RegisterUnaryTransitCallback( demand_callback) routing.AddDimensionWithVehicleCapacity( demand_callback_index, 0, # null capacity slack vehicleCap, # vehicle maximum capacities True, # start cumul to zero 'Capacity') # Setting first solution heuristic. search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = (solutionStrategy) search_parameters.local_search_metaheuristic = (localSearchStrategy) search_parameters.time_limit.seconds = timeLimit #search_parameters.lns_time_limit.seconds = 20 search_parameters.log_search = False # Solve the problem. assignment = routing.SolveWithParameters(search_parameters) print("Solver status: ", routing.status()) if assignment: vehicle_tours = print_solution(manager, routing, assignment, vehicle_count, customers) # calculate the cost of the solution; for each vehicle the length of the route obj = 0 for v in range(0, vehicle_count): vehicle_tour = vehicle_tours[v] #print("Vehicle %s - " %v, end="") #print(vehicle_tour) if len(vehicle_tour) > 0: obj += length(depot, customers[vehicle_tour[0]]) for i in range(0, len(vehicle_tour) - 1): obj += length(customers[vehicle_tour[i]], customers[vehicle_tour[i + 1]]) obj += length(customers[vehicle_tour[-1]], depot) # prepare the solution in the specified output format #print("Output") outputData = '%.2f' % obj + ' ' + str(0) + '\n' for v in range(0, vehicle_count): #outputData += str(depot.index) + ' ' + ' '.join([str(customer.index) for customer in vehicle_tours[v]]) + ' ' + str(depot.index) + '\n' v_tour = vehicle_tours[v] for node in range(0, len(v_tour)): outputData += str(v_tour[node]) + ' ' outputData += "\n" # build a trivial solution # assign customers to vehicles starting by the largest customer demands #vehicle_tours = [] #for v in range(0, vehicle_count): # vehicle_tours.append([]) #vehicle_tours[v].append(v) #print(vehicle_tours[v]) else: remaining_customers = set(customers) remaining_customers.remove(depot) for v in range(0, vehicle_count): # print "Start Vehicle: ",v vehicle_tours.append([]) capacity_remaining = vehicle_capacity #print("Vehicle %s " %v, end="") while sum([ capacity_remaining >= customer.demand for customer in remaining_customers ]) > 0: used = set() order = sorted(remaining_customers, key=lambda customer: -customer.demand) for customer in order: if capacity_remaining >= customer.demand: capacity_remaining -= customer.demand vehicle_tours[v].append(customer) # print ' add', ci, capacity_remaining used.add(customer) remaining_customers -= used # checks that the number of customers served is correct #assert sum([len(v) for v in vehicle_tours]) == len(customers) - 1 # calculate the cost of the solution; for each vehicle the length of the route obj = 0 for v in range(0, vehicle_count): vehicle_tour = vehicle_tours[v] #print("Vehicle %s - " %v, end="") #print(vehicle_tour) if len(vehicle_tour) > 0: obj += length(depot, vehicle_tour[0]) for i in range(0, len(vehicle_tour) - 1): obj += length(vehicle_tour[i], vehicle_tour[i + 1]) obj += length(vehicle_tour[-1], depot) # prepare the solution in the specified output format outputData = '%.2f' % obj + ' ' + str(0) + '\n' for v in range(0, vehicle_count): outputData += str(depot.index) + ' ' + ' '.join([ str(customer.index) for customer in vehicle_tours[v] ]) + ' ' + str(depot.index) + '\n' return outputData