def _run_single_problem(path_to_instance: Path, **kwargs): "Run single problem with solver arguments as in kwargs" instance_folder = path_to_instance.parent instance_type = path_to_instance.parent.stem instance_name = path_to_instance.name logger.info("Solving instance %s", instance_name) # Load data if instance_type == "cvrp": data = AugeratDataSet(path=instance_folder, instance_name=instance_name) elif instance_type == "cvrptw": data = SolomonDataSet(path=instance_folder, instance_name=instance_name) # Solve problem prob = VehicleRoutingProblem( data.G, load_capacity=data.max_load, time_windows=bool(instance_type == "cvrptw"), ) prob.solve(**kwargs) # Output results table = CsvTable( instance_name=instance_name, comp_time=prob.comp_time, best_known_solution=data.best_known_solution, instance_type=instance_type, ) table.from_vrpy_instance(prob)
def test_time_limit(self): prob = VehicleRoutingProblem(self.G, num_stops=3) start = time() prob.solve(cspy=False, time_limit=0.01) comp_time = time() - start assert comp_time < 0.01 + 0.15 # time_limit + time for mip assert prob.best_value == 70
def test_pricing_strategies(self): prob = VehicleRoutingProblem(self.G, num_stops=4) sol = [] for strategy in ["Exact", "BestPaths", "BestEdges1", "BestEdges2"]: prob.solve(pricing_strategy=strategy) sol.append(prob.best_value) assert len(set(sol)) == 1
def test_drop_nodes(self): prob = VehicleRoutingProblem(self.G, num_stops=3, num_vehicles=1, drop_penalty=100) prob.solve() assert prob.best_value == 240 assert prob.best_routes == {1: ["Source", 1, 2, 3, "Sink"]}
def test_cspy_stops_capacity(self): """Tests column generation procedure on toy graph with stop and capacity constraints """ prob = VehicleRoutingProblem(self.G, num_stops=3, load_capacity=10) prob.solve() assert prob.best_value == 80 assert set(prob.best_routes_load.values()) == {5, 10}
def test_clarke_wright(self): "Tests use of initial heuristic only" prob = VehicleRoutingProblem(self.G, num_stops=3) prob.solve(heuristic_only=True) assert prob.best_value == 70 assert prob.best_routes[0] in [ ["Source", 4, 5, "Sink"], ["Source", 1, 2, 3, "Sink"], ]
def test_LP_stops_elementarity(self): """Tests column generation procedure on toy graph""" self.G.add_edge(2, 1, cost=2) prob = VehicleRoutingProblem( self.G, num_stops=3, ) prob.solve(cspy=False) assert prob.best_value == 67
def test_LP_stops_time_windows(self): """Tests column generation procedure on toy graph""" prob = VehicleRoutingProblem( self.G, num_stops=3, time_windows=True, ) prob.solve(cspy=False) assert prob.best_value == 80
def setup(self): """ Augerat instance P-n16-k8.vrp """ data = AugeratDataSet(path="benchmarks/data/cvrp/", instance_name="P-n16-k8.vrp") self.G = data.G self.prob = VehicleRoutingProblem(self.G, load_capacity=data.max_load) self.solver_args = {"pricing_strategy": "BestPaths"}
def setup(self): G = DiGraph() G.add_edge(1, 2, cost=77.67) G.add_edge(1, 3, cost=0.0) G.add_edge(1, 4, cost=96.61) G.add_edge(1, 5, cost=0.0) G.add_edge(1, 6, cost=59.03) G.add_edge(2, 1, cost=77.67) G.add_edge(2, 3, cost=77.67) G.add_edge(2, 4, cost=64.85) G.add_edge(2, 5, cost=77.67) G.add_edge(2, 6, cost=62.2) G.add_edge(3, 1, cost=0.0) G.add_edge(3, 2, cost=77.67) G.add_edge(3, 4, cost=96.61) G.add_edge(3, 5, cost=0.0) G.add_edge(3, 6, cost=59.03) G.add_edge(4, 1, cost=96.61) G.add_edge(4, 2, cost=64.85) G.add_edge(4, 3, cost=96.61) G.add_edge(4, 5, cost=96.61) G.add_edge(4, 6, cost=39.82) G.add_edge(5, 1, cost=0.0) G.add_edge(5, 2, cost=77.67) G.add_edge(5, 3, cost=0.0) G.add_edge(5, 4, cost=96.61) G.add_edge(5, 6, cost=59.03) G.add_edge(6, 1, cost=59.03) G.add_edge(6, 2, cost=62.2) G.add_edge(6, 3, cost=59.03) G.add_edge(6, 4, cost=39.82) G.add_edge(6, 5, cost=59.03) G.add_edge("Source", 1, cost=18.03) G.add_edge(1, "Sink", cost=18.93) G.add_edge("Source", 2, cost=61.29) G.add_edge(2, "Sink", cost=61.29) G.add_edge("Source", 3, cost=18.03) G.add_edge(3, "Sink", cost=18.03) G.add_edge("Source", 4, cost=79.92) G.add_edge(4, "Sink", cost=79.92) G.add_edge("Source", 5, cost=18.03) G.add_edge(5, "Sink", cost=18.03) G.add_edge("Source", 6, cost=44.38) G.add_edge(6, "Sink", cost=44.38) G.nodes[1]["request"] = 2 G.nodes[1]["demand"] = 25000 G.nodes[2]["demand"] = -25000 G.nodes[3]["request"] = 4 G.nodes[3]["demand"] = 25000 G.nodes[4]["demand"] = -25000 G.nodes[5]["request"] = 6 G.nodes[5]["demand"] = 10000 G.nodes[6]["demand"] = -10000 self.prob = VehicleRoutingProblem(G, load_capacity=25000, pickup_delivery=True)
def test_LP_stops_capacity_duration(self): """Tests column generation procedure on toy graph""" prob = VehicleRoutingProblem( self.G, num_stops=3, load_capacity=10, duration=62, ) prob.solve(cspy=False) assert prob.best_value == 85
def test_cspy_stops(self): """Tests column generation procedure on toy graph with stop constraints""" prob = VehicleRoutingProblem(self.G, num_stops=3) prob.solve() assert prob.best_value == 70 assert prob.best_routes[1] in [ ["Source", 1, 2, 3, "Sink"], ["Source", 4, 5, "Sink"], ] assert set(prob.best_routes_cost.values()) == {30, 40}
def test_periodic(self): self.G.nodes[2]["frequency"] = 2 prob = VehicleRoutingProblem(self.G, num_stops=2, periodic=True) prob.solve() assert prob.best_value == 90 frequency = 0 for r in prob.best_routes: if 2 in prob.best_routes[r]: frequency += 1 assert frequency == 2
def test_initial_solution(self): prob = VehicleRoutingProblem(self.G, num_stops=4) routes = [ ["Source", 1, "Sink"], ["Source", 2, 3, "Sink"], ["Source", 4, 5, "Sink"], ] prob.solve(initial_routes=routes, cspy=False) assert prob.best_value == 70
def test_complete_lock(self): routes = [ ["Source", 1, "Sink"], ["Source", 2, "Sink"], ["Source", 3, "Sink"], ["Source", 4, "Sink"], ["Source", 5, "Sink"], ] prob = VehicleRoutingProblem(self.G) prob.solve(preassignments=routes) assert prob.best_value == 100
def test_dive(self): for (i, j) in self.G.edges(): self.G.edges[i, j]["cost"] = 2 * [self.G.edges[i, j]["cost"]] prob = VehicleRoutingProblem( self.G, load_capacity=[10, 15], fixed_cost=[10, 0], num_vehicles=[5, 1], mixed_fleet=True, ) prob.solve(dive=True) assert prob.best_value == 80
def setup(self): G = DiGraph() G.add_edge("Source", 1, cost=[1, 2]) G.add_edge("Source", 2, cost=[2, 4]) G.add_edge(1, "Sink", cost=[0, 0]) G.add_edge(2, "Sink", cost=[2, 4]) G.add_edge(1, 2, cost=[1, 2]) G.nodes[1]["demand"] = 13 G.nodes[2]["demand"] = 13 self.prob = VehicleRoutingProblem(G, mixed_fleet=True, load_capacity=[10, 15])
def test_cspy_stops_capacity_duration(self): """Tests column generation procedure on toy graph with stop, capacity and duration constraints """ prob = VehicleRoutingProblem(self.G, num_stops=3, load_capacity=10, duration=62) prob.solve(exact=False) assert prob.best_value == 85 assert set(prob.best_routes_duration.values()) == {41, 62} assert prob.node_load[1]["Sink"] in [5, 10]
def test_subproblem(self, n): data = SolomonDataSet(path="benchmarks/data/cvrptw/", instance_name="C101.txt", n_vertices=n) self.G = data.G self.prob = VehicleRoutingProblem(self.G, load_capacity=data.max_load, time_windows=True) self.prob.solve(cspy=False) best_value_lp = self.prob.best_value self.prob.solve(cspy=True) best_value_cspy = self.prob.best_value assert int(best_value_lp) == int(best_value_cspy)
def test_cspy_stops_time_windows(self): """Tests column generation procedure on toy graph with stop, capacity and time_window constraints """ prob = VehicleRoutingProblem( self.G, num_stops=3, time_windows=True, ) prob.solve() assert prob.best_value == 80 assert prob.departure_time[1]["Source"] == 0 assert prob.arrival_time[1]["Sink"] in [41, 62]
def test_mixed_fleet(self): for (i, j) in self.G.edges(): self.G.edges[i, j]["cost"] = 2 * [self.G.edges[i, j]["cost"]] prob = VehicleRoutingProblem( self.G, load_capacity=[10, 15], fixed_cost=[10, 0], num_vehicles=[5, 1], mixed_fleet=True, ) prob.solve() assert prob.best_value == 80 assert set(prob.best_routes_type.values()) == {0, 1}
def test_consistency_vrp(): """Tests consistency of input graph.""" G = Graph() with pytest.raises(TypeError): VehicleRoutingProblem(G) G = DiGraph() G.add_edge("Source", 1, cost=0) with pytest.raises(KeyError) and pytest.raises(NetworkXError): VehicleRoutingProblem(G) G.add_edge(1, "Sink") with pytest.raises(KeyError): VehicleRoutingProblem(G) G.edges[1, "Sink"]["cost"] = 1 G.add_edge("Sink", 2, cost=3) with pytest.raises(NetworkXError): VehicleRoutingProblem(G) with pytest.raises(NetworkXError): VehicleRoutingProblem(G) G.remove_edge("Sink", 2) with pytest.raises(TypeError): VehicleRoutingProblem(G, num_stops=3.5) with pytest.raises(TypeError): VehicleRoutingProblem(G, load_capacity=-10) with pytest.raises(TypeError): VehicleRoutingProblem(G, duration=0) G.remove_edge("Source", 1)
def test_num_vehicles_use_all(self): prob = VehicleRoutingProblem(self.G, num_stops=3, num_vehicles=2, use_all_vehicles=True, drop_penalty=100) prob.solve() assert len(prob.best_routes) == 2 prob.num_vehicles = 3 prob.solve() assert len(prob.best_routes) == 3 prob.num_vehicles = 4 prob.solve() assert len(prob.best_routes) == 4
class TestsSolomon: def setup(self): """ Solomon instance c101, 25 first nodes only including depot """ data = SolomonDataSet(path="benchmarks/data/cvrptw/", instance_name="C101.txt", n_vertices=25) self.G = data.G self.n_vertices = 25 self.prob = VehicleRoutingProblem(self.G, load_capacity=data.max_load, time_windows=True) initial_routes = [ ["Source", 13, 17, 18, 19, 15, 16, 14, 12, 1, "Sink"], ["Source", 20, 24, 23, 22, 21, "Sink"], ["Source", 5, 3, 7, 8, 10, 11, 6, 4, 2, "Sink"], ["Source", 9, "Sink"], ] # Set repeating solver arguments self.solver_args = { "pricing_strategy": "BestPaths", "initial_routes": initial_routes } def test_setup_instance_name(self): assert self.G.graph["name"] == "C101." + str(self.n_vertices) def test_setup_vehicle_capacity(self): assert self.G.graph["vehicle_capacity"] == 200 def test_setup_nodes(self): # extra node for the Sink assert len(self.G.nodes()) == self.n_vertices + 1 def test_setup_edges(self): assert len( self.G.edges()) == self.n_vertices * (self.n_vertices - 1) + 1 def test_subproblem_lp(self): # benchmark result # e.g., in Feillet et al. (2004) self.prob.solve(**self.solver_args, cspy=False) assert round(self.prob.best_value, -1) in [190, 200] def test_subproblem_cspy(self): self.prob.solve(**self.solver_args, cspy=True) assert round(self.prob.best_value, -1) in [190, 200]
def test_pick_up_delivery(self): self.G.nodes[2]["request"] = 5 self.G.nodes[2]["demand"] = 10 self.G.nodes[3]["demand"] = 10 self.G.nodes[3]["request"] = 4 self.G.nodes[4]["demand"] = -10 self.G.nodes[5]["demand"] = -10 self.G.add_edge(2, 5, cost=10) self.G.remove_node(1) prob = VehicleRoutingProblem( self.G, load_capacity=15, pickup_delivery=True, ) prob.solve(pricing_strategy="Exact", cspy=False) assert prob.best_value == 65
class TestIssue110: def setup(self): G = DiGraph() G.add_edge("Source", 1, cost=[1, 2]) G.add_edge("Source", 2, cost=[2, 4]) G.add_edge(1, "Sink", cost=[0, 0]) G.add_edge(2, "Sink", cost=[2, 4]) G.add_edge(1, 2, cost=[1, 2]) G.nodes[1]["demand"] = 13 G.nodes[2]["demand"] = 13 self.prob = VehicleRoutingProblem(G, mixed_fleet=True, load_capacity=[10, 15]) def test_node_load(self): self.prob.solve() assert self.prob.best_routes_type == {1: 1, 2: 1}
def test_LP_schedule(self): """Tests column generation procedure on toy graph""" prob = VehicleRoutingProblem( self.G, num_stops=3, time_windows=True, ) prob.solve(cspy=False) prob.check_arrival_time() prob.check_departure_time()
def setup(self): self.G = DiGraph() self.G.add_edge("Source", 1, cost=5) self.G.add_edge("Source", 2, cost=5) self.G.add_edge(1, "Sink", cost=5) self.G.add_edge(2, "Sink", cost=5) self.G.add_edge(1, 2, cost=1) self.G.nodes[1]["lower"] = 0 self.G.nodes[1]["upper"] = 20 self.G.nodes[2]["lower"] = 0 self.G.nodes[2]["upper"] = 20 self.G.nodes[1]["service_time"] = 5 self.G.nodes[2]["service_time"] = 5 self.G.nodes[1]["demand"] = 8 self.G.nodes[2]["demand"] = 8 self.prob = VehicleRoutingProblem(self.G, load_capacity=10, time_windows=True)
def test_cspy_schedule(self): """Tests if final schedule is time-window feasible""" prob = VehicleRoutingProblem( self.G, num_stops=3, time_windows=True, ) prob.solve() assert prob.departure_time[1]["Source"] == 0 assert prob.arrival_time[1]["Sink"] in [41, 62] prob.check_arrival_time() prob.check_departure_time()
def setup(self): # Transform distance matrix to DiGraph A = matrix(DISTANCES, dtype=[("cost", int)]) G_d = from_numpy_matrix(A, create_using=DiGraph()) # Transform time matrix to DiGraph A = matrix(TRAVEL_TIMES, dtype=[("time", int)]) G_t = from_numpy_matrix(A, create_using=DiGraph()) # Merge G = compose(G_d, G_t) # Set time windows set_node_attributes(G, values=TIME_WINDOWS_LOWER, name="lower") set_node_attributes(G, values=TIME_WINDOWS_UPPER, name="upper") # Set demand and collect volumes set_node_attributes(G, values=DEMANDS, name="demand") set_node_attributes(G, values=COLLECT, name="collect") # Relabel depot self.G = relabel_nodes(G, {0: "Source", 17: "Sink"}) # Define VRP self.prob = VehicleRoutingProblem(self.G)