From be220948a3569f167b73b030e920f2ed68169dca Mon Sep 17 00:00:00 2001 From: Mizux Seiha Date: Thu, 11 Apr 2024 10:56:30 +0200 Subject: [PATCH] python: run black on all files --- examples/python/arc_flow_cutting_stock_sat.py | 114 ++++---- examples/python/testdata/BUILD.bazel | 1 - .../constraint_solver/samples/cvrp_reload.py | 243 ++++++++++-------- .../samples/vrp_breaks_from_start.py | 78 +++--- .../samples/vrp_items_to_deliver.py | 91 +++---- .../constraint_solver/samples/vrp_node_max.py | 1 - .../samples/vrp_nodes_indices.py | 48 ++-- .../samples/vrp_time_windows_per_vehicles.py | 70 ++--- .../python/linear_solver_natural_api.py | 1 + ortools/linear_solver/python/lp_api_test.py | 50 ++-- ortools/linear_solver/python/lp_test.py | 204 ++++++++------- .../compute_infeasible_subsystem_result.py | 12 +- ortools/math_opt/python/expressions.py | 6 +- ortools/math_opt/python/hash_model_storage.py | 12 +- ortools/math_opt/python/model.py | 72 ++---- ortools/math_opt/python/result.py | 78 +++--- ortools/math_opt/python/solution.py | 16 +- 17 files changed, 574 insertions(+), 523 deletions(-) diff --git a/examples/python/arc_flow_cutting_stock_sat.py b/examples/python/arc_flow_cutting_stock_sat.py index 60285ee810..ec300e1a0f 100644 --- a/examples/python/arc_flow_cutting_stock_sat.py +++ b/examples/python/arc_flow_cutting_stock_sat.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 # Copyright 2010-2024 Google LLC # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -10,15 +11,16 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -"""Cutting stock problem with the objective to minimize wasted space.""" +"""Cutting stock problem with the objective to minimize wasted space.""" import collections import time -import numpy as np from absl import app from absl import flags +import numpy as np + from google.protobuf import text_format from ortools.linear_solver.python import model_builder as mb from ortools.sat.python import cp_model @@ -26,13 +28,14 @@ from ortools.sat.python import cp_model FLAGS = flags.FLAGS _OUTPUT_PROTO = flags.DEFINE_string( - 'output_proto', '', 'Output file to write the cp_model proto to.') + "output_proto", "", "Output file to write the cp_model proto to." +) _PARAMS = flags.DEFINE_string( - 'params', - 'num_search_workers:8,log_search_progress:true,max_time_in_seconds:10', - 'Sat solver parameters.') -_SOLVER = flags.DEFINE_string( - 'solver', 'sat', 'Method used to solve: sat, mip.') + "params", + "num_search_workers:8,log_search_progress:true,max_time_in_seconds:10", + "Sat solver parameters.", +) +_SOLVER = flags.DEFINE_string("solver", "sat", "Method used to solve: sat, mip.") DESIRED_LENGTHS = [ @@ -104,9 +107,9 @@ def create_state_graph(items, max_capacity): states.append(new_state) state_to_index[new_state] = new_state_index # Add the transition - transitions.append([ - current_state_index, new_state_index, item_index, card + 1 - ]) + transitions.append( + [current_state_index, new_state_index, item_index, card + 1] + ) return states, transitions @@ -114,14 +117,19 @@ def create_state_graph(items, max_capacity): def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: str): """Solve the cutting stock with arc-flow and the CP-SAT solver.""" items = regroup_and_count(DESIRED_LENGTHS) - print('Items:', items) + print("Items:", items) num_items = len(DESIRED_LENGTHS) max_capacity = max(POSSIBLE_CAPACITIES) states, transitions = create_state_graph(items, max_capacity) - print('Dynamic programming has generated', len(states), 'states and', - len(transitions), 'transitions') + print( + "Dynamic programming has generated", + len(states), + "states and", + len(transitions), + "transitions", + ) incoming_vars = collections.defaultdict(list) outgoing_vars = collections.defaultdict(list) @@ -139,8 +147,8 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st count = items[item_index][1] max_count = count // card count_var = model.NewIntVar( - 0, max_count, - 'i%i_f%i_t%i_C%s' % (item_index, incoming, outgoing, card)) + 0, max_count, "i%i_f%i_t%i_C%s" % (item_index, incoming, outgoing, card) + ) incoming_vars[incoming].append(count_var) outgoing_vars[outgoing].append(count_var) item_vars[item_index].append(count_var) @@ -150,7 +158,7 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st for state_index, state in enumerate(states): if state_index == 0: continue - exit_var = model.NewIntVar(0, num_items, 'e%i' % state_index) + exit_var = model.NewIntVar(0, num_items, "e%i" % state_index) outgoing_vars[state_index].append(exit_var) incoming_sink_vars.append(exit_var) price = price_usage(state, POSSIBLE_CAPACITIES) @@ -159,8 +167,7 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st # Flow conservation for state_index in range(1, len(states)): - model.Add( - sum(incoming_vars[state_index]) == sum(outgoing_vars[state_index])) + model.Add(sum(incoming_vars[state_index]) == sum(outgoing_vars[state_index])) # Flow going out of the source must go in the sink model.Add(sum(outgoing_vars[0]) == sum(incoming_sink_vars)) @@ -169,13 +176,17 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st for item_index, size_and_count in enumerate(items): num_arcs = len(item_vars[item_index]) model.Add( - sum(item_vars[item_index][i] * item_coeffs[item_index][i] - for i in range(num_arcs)) == size_and_count[1]) + sum( + item_vars[item_index][i] * item_coeffs[item_index][i] + for i in range(num_arcs) + ) + == size_and_count[1] + ) # Objective is the sum of waste model.Minimize( - sum(objective_vars[i] * objective_coeffs[i] - for i in range(len(objective_vars)))) + sum(objective_vars[i] * objective_coeffs[i] for i in range(len(objective_vars))) + ) # Output model proto to file. if output_proto_file: @@ -192,13 +203,18 @@ def solve_cutting_stock_with_arc_flow_and_sat(output_proto_file: str, params: st def solve_cutting_stock_with_arc_flow_and_mip(): """Solve the cutting stock with arc-flow and a MIP solver.""" items = regroup_and_count(DESIRED_LENGTHS) - print('Items:', items) + print("Items:", items) num_items = len(DESIRED_LENGTHS) max_capacity = max(POSSIBLE_CAPACITIES) states, transitions = create_state_graph(items, max_capacity) - print('Dynamic programming has generated', len(states), 'states and', - len(transitions), 'transitions') + print( + "Dynamic programming has generated", + len(states), + "states and", + len(transitions), + "transitions", + ) incoming_vars = collections.defaultdict(list) outgoing_vars = collections.defaultdict(list) @@ -216,8 +232,10 @@ def solve_cutting_stock_with_arc_flow_and_mip(): for outgoing, incoming, item_index, card in transitions: count = items[item_index][1] count_var = model.new_int_var( - 0, count, 'a%i_i%i_f%i_t%i_c%i' % (var_index, item_index, incoming, - outgoing, card)) + 0, + count, + "a%i_i%i_f%i_t%i_c%i" % (var_index, item_index, incoming, outgoing, card), + ) var_index += 1 incoming_vars[incoming].append(count_var) outgoing_vars[outgoing].append(count_var) @@ -227,7 +245,7 @@ def solve_cutting_stock_with_arc_flow_and_mip(): for state_index, state in enumerate(states): if state_index == 0: continue - exit_var = model.new_int_var(0, num_items, 'e%i' % state_index) + exit_var = model.new_int_var(0, num_items, "e%i" % state_index) outgoing_vars[state_index].append(exit_var) incoming_sink_vars.append(exit_var) price = price_usage(state, POSSIBLE_CAPACITIES) @@ -237,44 +255,52 @@ def solve_cutting_stock_with_arc_flow_and_mip(): # Flow conservation for state_index in range(1, len(states)): model.add( - mb.LinearExpr.sum(incoming_vars[state_index]) == mb.LinearExpr.sum( - outgoing_vars[state_index])) + mb.LinearExpr.sum(incoming_vars[state_index]) + == mb.LinearExpr.sum(outgoing_vars[state_index]) + ) # Flow going out of the source must go in the sink model.add( - mb.LinearExpr.sum(outgoing_vars[0]) == mb.LinearExpr.sum( - incoming_sink_vars)) + mb.LinearExpr.sum(outgoing_vars[0]) == mb.LinearExpr.sum(incoming_sink_vars) + ) # Items must be placed for item_index, size_and_count in enumerate(items): num_arcs = len(item_vars[item_index]) model.add( - mb.LinearExpr.sum([item_vars[item_index][i] * item_coeffs[item_index][i] - for i in range(num_arcs)]) == size_and_count[1]) + mb.LinearExpr.sum( + [ + item_vars[item_index][i] * item_coeffs[item_index][i] + for i in range(num_arcs) + ] + ) + == size_and_count[1] + ) # Objective is the sum of waste model.minimize(np.dot(objective_vars, objective_coeffs)) - solver = mb.ModelSolver('scip') + solver = mb.ModelSolver("scip") solver.enable_output(True) status = solver.solve(model) ### Output the solution. if status == mb.SolveStatus.OPTIMAL or status == mb.SolveStatus.FEASIBLE: - print('Objective value = %f found in %.2f s' % - (solver.objective_value, time.time() - start_time)) + print( + "Objective value = %f found in %.2f s" + % (solver.objective_value, time.time() - start_time) + ) else: - print('No solution') + print("No solution") def main(_): - """Main function""" - if _SOLVER.value == 'sat': - solve_cutting_stock_with_arc_flow_and_sat(_OUTPUT_PROTO.value, - _PARAMS.value) + """Main function.""" + if _SOLVER.value == "sat": + solve_cutting_stock_with_arc_flow_and_sat(_OUTPUT_PROTO.value, _PARAMS.value) else: # 'mip' solve_cutting_stock_with_arc_flow_and_mip() -if __name__ == '__main__': +if __name__ == "__main__": app.run(main) diff --git a/examples/python/testdata/BUILD.bazel b/examples/python/testdata/BUILD.bazel index 7d9df48d90..210dd5ec30 100644 --- a/examples/python/testdata/BUILD.bazel +++ b/examples/python/testdata/BUILD.bazel @@ -18,4 +18,3 @@ exports_files( "salbp_20_1.alb", ], ) - diff --git a/ortools/constraint_solver/samples/cvrp_reload.py b/ortools/constraint_solver/samples/cvrp_reload.py index 4cbbb5eb7f..111fa5db6d 100755 --- a/ortools/constraint_solver/samples/cvrp_reload.py +++ b/ortools/constraint_solver/samples/cvrp_reload.py @@ -78,52 +78,69 @@ def create_data_model(): (3, 7), (6, 7), (0, 8), - (7, 8) + (7, 8), ] # Compute locations in meters using the block dimension defined as follow # Manhattan average block: 750ft x 264ft -> 228m x 80m # here we use: 114m x 80m city block # src: https://nyti.ms/2GDoRIe 'NY Times: Know Your distance' - data['locations'] = [(l[0] * 114, l[1] * 80) for l in _locations] - data['num_locations'] = len(data['locations']) - data['demands'] = \ - [0, # depot - -_capacity, # unload depot_first - -_capacity, # unload depot_second - -_capacity, # unload depot_third - -_capacity, # unload depot_fourth - -_capacity, # unload depot_fifth - 3, 3, # 1, 2 - 3, 4, # 3, 4 - 3, 4, # 5, 6 - 8, 8, # 7, 8 - 3, 3, # 9,10 - 3, 3, # 11,12 - 4, 4, # 13, 14 - 8, 8] # 15, 16 - data['time_per_demand_unit'] = 5 # 5 minutes/unit - data['time_windows'] = \ - [(0, 0), # depot - (0, 1000), # unload depot_first - (0, 1000), # unload depot_second - (0, 1000), # unload depot_third - (0, 1000), # unload depot_fourth - (0, 1000), # unload depot_fifth - (75, 850), (75, 850), # 1, 2 - (60, 700), (45, 550), # 3, 4 - (0, 800), (50, 600), # 5, 6 - (0, 1000), (10, 200), # 7, 8 - (0, 1000), (75, 850), # 9, 10 - (85, 950), (5, 150), # 11, 12 - (15, 250), (10, 200), # 13, 14 - (45, 550), (30, 400)] # 15, 16 - data['num_vehicles'] = 3 - data['vehicle_capacity'] = _capacity - data['vehicle_max_distance'] = 10_000 - data['vehicle_max_time'] = 1_500 - data[ - 'vehicle_speed'] = 5 * 60 / 3.6 # Travel speed: 5km/h to convert in m/min - data['depot'] = 0 + data["locations"] = [(l[0] * 114, l[1] * 80) for l in _locations] + data["num_locations"] = len(data["locations"]) + data["demands"] = [ + 0, # depot + -_capacity, # unload depot_first + -_capacity, # unload depot_second + -_capacity, # unload depot_third + -_capacity, # unload depot_fourth + -_capacity, # unload depot_fifth + 3, + 3, # 1, 2 + 3, + 4, # 3, 4 + 3, + 4, # 5, 6 + 8, + 8, # 7, 8 + 3, + 3, # 9,10 + 3, + 3, # 11,12 + 4, + 4, # 13, 14 + 8, + 8, + ] # 15, 16 + data["time_per_demand_unit"] = 5 # 5 minutes/unit + data["time_windows"] = [ + (0, 0), # depot + (0, 1000), # unload depot_first + (0, 1000), # unload depot_second + (0, 1000), # unload depot_third + (0, 1000), # unload depot_fourth + (0, 1000), # unload depot_fifth + (75, 850), + (75, 850), # 1, 2 + (60, 700), + (45, 550), # 3, 4 + (0, 800), + (50, 600), # 5, 6 + (0, 1000), + (10, 200), # 7, 8 + (0, 1000), + (75, 850), # 9, 10 + (85, 950), + (5, 150), # 11, 12 + (15, 250), + (10, 200), # 13, 14 + (45, 550), + (30, 400), + ] # 15, 16 + data["num_vehicles"] = 3 + data["vehicle_capacity"] = _capacity + data["vehicle_max_distance"] = 10_000 + data["vehicle_max_time"] = 1_500 + data["vehicle_speed"] = 5 * 60 / 3.6 # Travel speed: 5km/h to convert in m/min + data["depot"] = 0 return data @@ -132,30 +149,29 @@ def create_data_model(): ####################### def manhattan_distance(position_1, position_2): """Computes the Manhattan distance between two points""" - return (abs(position_1[0] - position_2[0]) + - abs(position_1[1] - position_2[1])) + return abs(position_1[0] - position_2[0]) + abs(position_1[1] - position_2[1]) def create_distance_evaluator(data): """Creates callback to return distance between points.""" _distances = {} # precompute distance between location to have distance callback in O(1) - for from_node in range(data['num_locations']): + for from_node in range(data["num_locations"]): _distances[from_node] = {} - for to_node in range(data['num_locations']): + for to_node in range(data["num_locations"]): if from_node == to_node: _distances[from_node][to_node] = 0 # Forbid start/end/reload node to be consecutive. elif from_node in range(6) and to_node in range(6): - _distances[from_node][to_node] = data['vehicle_max_distance'] + _distances[from_node][to_node] = data["vehicle_max_distance"] else: - _distances[from_node][to_node] = (manhattan_distance( - data['locations'][from_node], data['locations'][to_node])) + _distances[from_node][to_node] = manhattan_distance( + data["locations"][from_node], data["locations"][to_node] + ) def distance_evaluator(manager, from_node, to_node): """Returns the manhattan distance between the two nodes""" - return _distances[manager.IndexToNode(from_node)][manager.IndexToNode( - to_node)] + return _distances[manager.IndexToNode(from_node)][manager.IndexToNode(to_node)] return distance_evaluator @@ -163,13 +179,14 @@ def create_distance_evaluator(data): def add_distance_dimension(routing, manager, data, distance_evaluator_index): """Add Global Span constraint""" del manager - distance = 'Distance' + distance = "Distance" routing.AddDimension( distance_evaluator_index, 0, # null slack - data['vehicle_max_distance'], # maximum distance per vehicle + data["vehicle_max_distance"], # maximum distance per vehicle True, # start cumul to zero - distance) + distance, + ) distance_dimension = routing.GetDimensionOrDie(distance) # Try to minimize the max distance among vehicles. # /!\ It doesn't mean the standard deviation is minimized @@ -178,7 +195,7 @@ def add_distance_dimension(routing, manager, data, distance_evaluator_index): def create_demand_evaluator(data): """Creates callback to get demands at each location.""" - _demands = data['demands'] + _demands = data["demands"] def demand_evaluator(manager, from_node): """Returns the demand of the current node""" @@ -189,14 +206,15 @@ def create_demand_evaluator(data): def add_capacity_constraints(routing, manager, data, demand_evaluator_index): """Adds capacity constraint""" - vehicle_capacity = data['vehicle_capacity'] - capacity = 'Capacity' + vehicle_capacity = data["vehicle_capacity"] + capacity = "Capacity" routing.AddDimension( demand_evaluator_index, vehicle_capacity, vehicle_capacity, True, # start cumul to zero - capacity) + capacity, + ) # Add Slack for reseting to zero unload depot nodes. # e.g. vehicle with load 10/15 arrives at node 1 (depot unload) @@ -208,7 +226,7 @@ def add_capacity_constraints(routing, manager, data, demand_evaluator_index): routing.AddDisjunction([node_index], 0) # Allow to drop regular node with a cost. - for node in range(6, len(data['demands'])): + for node in range(6, len(data["demands"])): node_index = manager.NodeToIndex(node) capacity_dimension.SlackVar(node_index).SetValue(0) routing.AddDisjunction([node_index], 100_000) @@ -219,52 +237,56 @@ def create_time_evaluator(data): def service_time(data, node): """Gets the service time for the specified location.""" - return abs(data['demands'][node]) * data['time_per_demand_unit'] + return abs(data["demands"][node]) * data["time_per_demand_unit"] def travel_time(data, from_node, to_node): """Gets the travel times between two locations.""" if from_node == to_node: travel_time = 0 else: - travel_time = manhattan_distance( - data['locations'][from_node], - data['locations'][to_node]) / data['vehicle_speed'] + travel_time = ( + manhattan_distance( + data["locations"][from_node], data["locations"][to_node] + ) + / data["vehicle_speed"] + ) return travel_time _total_time = {} # precompute total time to have time callback in O(1) - for from_node in range(data['num_locations']): + for from_node in range(data["num_locations"]): _total_time[from_node] = {} - for to_node in range(data['num_locations']): + for to_node in range(data["num_locations"]): if from_node == to_node: _total_time[from_node][to_node] = 0 else: _total_time[from_node][to_node] = int( - service_time(data, from_node) + - travel_time(data, from_node, to_node)) + service_time(data, from_node) + + travel_time(data, from_node, to_node) + ) def time_evaluator(manager, from_node, to_node): """Returns the total time between the two nodes""" - return _total_time[manager.IndexToNode(from_node)][manager.IndexToNode( - to_node)] + return _total_time[manager.IndexToNode(from_node)][manager.IndexToNode(to_node)] return time_evaluator def add_time_window_constraints(routing, manager, data, time_evaluator): """Add Time windows constraint""" - time = 'Time' - max_time = data['vehicle_max_time'] + time = "Time" + max_time = data["vehicle_max_time"] routing.AddDimension( time_evaluator, max_time, # allow waiting time max_time, # maximum time per vehicle False, # don't force start cumul to zero since we are giving TW to start nodes - time) + 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']): + for location_idx, time_window in enumerate(data["time_windows"]): if location_idx == 0: continue index = manager.NodeToIndex(location_idx) @@ -272,70 +294,73 @@ def add_time_window_constraints(routing, manager, data, time_evaluator): 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']): + 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]) + time_dimension.CumulVar(index).SetRange( + data["time_windows"][0][0], data["time_windows"][0][1] + ) routing.AddToAssignment(time_dimension.SlackVar(index)) # Warning: Slack var is not defined for vehicle's end node - #routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id))) + # routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id))) ########### # Printer # ########### -def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals +def print_solution( + data, manager, routing, assignment +): # pylint:disable=too-many-locals """Prints assignment on console""" - print(f'Objective: {assignment.ObjectiveValue()}') + print(f"Objective: {assignment.ObjectiveValue()}") total_distance = 0 total_load = 0 total_time = 0 - capacity_dimension = routing.GetDimensionOrDie('Capacity') - time_dimension = routing.GetDimensionOrDie('Time') + capacity_dimension = routing.GetDimensionOrDie("Capacity") + time_dimension = routing.GetDimensionOrDie("Time") dropped = [] for order in range(6, routing.nodes()): index = manager.NodeToIndex(order) if assignment.Value(routing.NextVar(index)) == index: dropped.append(order) - print(f'dropped orders: {dropped}') + print(f"dropped orders: {dropped}") for reload in range(1, 6): index = manager.NodeToIndex(reload) if assignment.Value(routing.NextVar(index)) == index: dropped.append(reload) - print(f'dropped reload stations: {dropped}') + print(f"dropped reload stations: {dropped}") - for vehicle_id in range(data['num_vehicles']): + for vehicle_id in range(data["num_vehicles"]): index = routing.Start(vehicle_id) - plan_output = f'Route for vehicle {vehicle_id}:\n' + plan_output = f"Route for vehicle {vehicle_id}:\n" distance = 0 while not routing.IsEnd(index): load_var = capacity_dimension.CumulVar(index) time_var = time_dimension.CumulVar(index) plan_output += ( - f' {manager.IndexToNode(index)} ' - f'Load({assignment.Min(load_var)}) ' - f'Time({assignment.Min(time_var)},{assignment.Max(time_var)}) ->' + f" {manager.IndexToNode(index)} " + f"Load({assignment.Min(load_var)}) " + f"Time({assignment.Min(time_var)},{assignment.Max(time_var)}) ->" ) previous_index = index index = assignment.Value(routing.NextVar(index)) - distance += routing.GetArcCostForVehicle(previous_index, index, - vehicle_id) + distance += routing.GetArcCostForVehicle(previous_index, index, vehicle_id) load_var = capacity_dimension.CumulVar(index) time_var = time_dimension.CumulVar(index) plan_output += ( - f' {manager.IndexToNode(index)} ' - f'Load({assignment.Min(load_var)}) ' - f'Time({assignment.Min(time_var)},{assignment.Max(time_var)})\n') - plan_output += f'Distance of the route: {distance}m\n' - plan_output += f'Load of the route: {assignment.Min(load_var)}\n' - plan_output += f'Time of the route: {assignment.Min(time_var)}min\n' + f" {manager.IndexToNode(index)} " + f"Load({assignment.Min(load_var)}) " + f"Time({assignment.Min(time_var)},{assignment.Max(time_var)})\n" + ) + plan_output += f"Distance of the route: {distance}m\n" + plan_output += f"Load of the route: {assignment.Min(load_var)}\n" + plan_output += f"Time of the route: {assignment.Min(time_var)}min\n" print(plan_output) total_distance += distance total_load += assignment.Min(load_var) total_time += assignment.Min(time_var) - print(f'Total Distance of all routes: {total_distance}m') - print(f'Total Load of all routes: {total_load}') - print(f'Total Time of all routes: {total_time}min') + print(f"Total Distance of all routes: {total_distance}m") + print(f"Total Load of all routes: {total_load}") + print(f"Total Time of all routes: {total_time}min") ######## @@ -347,15 +372,17 @@ def main(): data = create_data_model() # Create the routing index manager - manager = pywrapcp.RoutingIndexManager(data['num_locations'], - data['num_vehicles'], data['depot']) + manager = pywrapcp.RoutingIndexManager( + data["num_locations"], data["num_vehicles"], data["depot"] + ) # Create Routing Model routing = pywrapcp.RoutingModel(manager) # Define weight of each edge distance_evaluator_index = routing.RegisterTransitCallback( - partial(create_distance_evaluator(data), manager)) + partial(create_distance_evaluator(data), manager) + ) routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index) # Add Distance constraint to minimize the longuest route @@ -363,20 +390,24 @@ def main(): # Add Capacity constraint demand_evaluator_index = routing.RegisterUnaryTransitCallback( - partial(create_demand_evaluator(data), manager)) + partial(create_demand_evaluator(data), manager) + ) add_capacity_constraints(routing, manager, data, demand_evaluator_index) # Add Time Window constraint time_evaluator_index = routing.RegisterTransitCallback( - partial(create_time_evaluator(data), manager)) + partial(create_time_evaluator(data), manager) + ) add_time_window_constraints(routing, manager, data, time_evaluator_index) # 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-member + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) # pylint: disable=no-member search_parameters.local_search_metaheuristic = ( - routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) search_parameters.time_limit.FromSeconds(3) # Solve the problem. @@ -387,5 +418,5 @@ def main(): print("No solution found !") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/ortools/constraint_solver/samples/vrp_breaks_from_start.py b/ortools/constraint_solver/samples/vrp_breaks_from_start.py index 1f3af351e0..db3effc457 100755 --- a/ortools/constraint_solver/samples/vrp_breaks_from_start.py +++ b/ortools/constraint_solver/samples/vrp_breaks_from_start.py @@ -33,9 +33,9 @@ from ortools.constraint_solver import pywrapcp def create_data_model(): """Stores the data for the problem.""" data = {} - data['num_vehicles'] = 4 - data['depot'] = 0 - data['time_matrix'] = [ + data["num_vehicles"] = 4 + data["depot"] = 0 + data["time_matrix"] = [ [0, 27, 38, 34, 29, 13, 25, 9, 15, 9, 26, 25, 19, 17, 23, 38, 33], [27, 0, 34, 15, 9, 25, 36, 17, 34, 37, 54, 29, 24, 33, 50, 43, 60], [38, 34, 0, 49, 43, 25, 13, 40, 23, 37, 20, 63, 58, 56, 39, 77, 37], @@ -55,9 +55,9 @@ def create_data_model(): [33, 60, 37, 67, 62, 35, 24, 42, 25, 23, 17, 42, 36, 26, 9, 39, 0], ] # 15 min of service time - data['service_time'] = [15] * len(data['time_matrix']) - data['service_time'][data['depot']] = 0 - assert len(data['time_matrix']) == len(data['service_time']) + data["service_time"] = [15] * len(data["time_matrix"]) + data["service_time"][data["depot"]] = 0 + assert len(data["time_matrix"]) == len(data["service_time"]) return data # [END data_model] @@ -65,38 +65,40 @@ def create_data_model(): # [START solution_printer] def print_solution(manager, routing, solution): """Prints solution on console.""" - print(f'Objective: {solution.ObjectiveValue()}') + print(f"Objective: {solution.ObjectiveValue()}") - print('Breaks:') + print("Breaks:") intervals = solution.IntervalVarContainer() for i in range(intervals.Size()): brk = intervals.Element(i) if brk.PerformedValue() == 1: - print(f'{brk.Var().Name()}: ' + - f'Start({brk.StartValue()}) Duration({brk.DurationValue()})') + print( + f"{brk.Var().Name()}: " + + f"Start({brk.StartValue()}) Duration({brk.DurationValue()})" + ) else: - print(f'{brk.Var().Name()}: Unperformed') + print(f"{brk.Var().Name()}: Unperformed") - time_dimension = routing.GetDimensionOrDie('Time') + time_dimension = routing.GetDimensionOrDie("Time") total_time = 0 for vehicle_id in range(manager.GetNumberOfVehicles()): index = routing.Start(vehicle_id) - plan_output = f'Route for vehicle {vehicle_id}:\n' + plan_output = f"Route for vehicle {vehicle_id}:\n" while not routing.IsEnd(index): time_var = time_dimension.CumulVar(index) if routing.IsStart(index): start_time = solution.Value(time_var) - plan_output += f'{manager.IndexToNode(index)} ' - plan_output += f'Time({solution.Value(time_var)}) -> ' + plan_output += f"{manager.IndexToNode(index)} " + plan_output += f"Time({solution.Value(time_var)}) -> " index = solution.Value(routing.NextVar(index)) time_var = time_dimension.CumulVar(index) - plan_output += f'{manager.IndexToNode(index)} ' - plan_output += f'Time({solution.Value(time_var)})' + plan_output += f"{manager.IndexToNode(index)} " + plan_output += f"Time({solution.Value(time_var)})" print(plan_output) route_time = solution.Value(time_var) - start_time - print(f'Time of the route: {route_time}min\n') + print(f"Time of the route: {route_time}min\n") total_time += route_time - print(f'Total time of all routes: {total_time}min') + print(f"Total time of all routes: {total_time}min") # [END solution_printer] @@ -109,8 +111,9 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), - data['num_vehicles'], data['depot']) + manager = pywrapcp.RoutingIndexManager( + len(data["time_matrix"]), data["num_vehicles"], data["depot"] + ) # [END index_manager] # Create Routing Model. @@ -118,7 +121,6 @@ def main(): routing = pywrapcp.RoutingModel(manager) # [END routing_model] - # Create and register a transit callback. # [START transit_callback] def time_callback(from_index, to_index): @@ -126,7 +128,7 @@ def main(): # 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] + return data["time_matrix"][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(time_callback) # [END transit_callback] @@ -137,13 +139,14 @@ def main(): # [END arc_cost] # Add Time Windows constraint. - time = 'Time' + time = "Time" routing.AddDimension( transit_callback_index, 10, # need optional waiting time to place break 180, # maximum time per vehicle False, # Don't force start cumul to zero. - time) + time, + ) time_dimension = routing.GetDimensionOrDie(time) time_dimension.SetGlobalSpanCostCoefficient(10) @@ -158,29 +161,32 @@ def main(): node_visit_transit = [0] * routing.Size() for index in range(routing.Size()): node = manager.IndexToNode(index) - node_visit_transit[index] = data['service_time'][node] + node_visit_transit[index] = data["service_time"][node] # Add a break lasting 5 minutes, start between 25 and 45 minutes after route start for v in range(manager.GetNumberOfVehicles()): start_var = time_dimension.CumulVar(routing.Start(v)) - break_start = routing.solver().Sum( - [routing.solver().IntVar(25, 45), start_var]) + break_start = routing.solver().Sum([routing.solver().IntVar(25, 45), start_var]) break_intervals = [ - routing.solver().FixedDurationIntervalVar(break_start, 5, - f'Break for vehicle {v}') + routing.solver().FixedDurationIntervalVar( + break_start, 5, f"Break for vehicle {v}" + ) ] - time_dimension.SetBreakIntervalsOfVehicle(break_intervals, v, - node_visit_transit) + time_dimension.SetBreakIntervalsOfVehicle( + break_intervals, v, 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) + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) search_parameters.local_search_metaheuristic = ( - routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) # search_parameters.log_search = True search_parameters.time_limit.FromSeconds(2) # [END parameters] @@ -195,10 +201,10 @@ def main(): if solution: print_solution(manager, routing, solution) else: - print('No solution found !') + print("No solution found !") # [END print_solution] -if __name__ == '__main__': +if __name__ == "__main__": main() # [END program] diff --git a/ortools/constraint_solver/samples/vrp_items_to_deliver.py b/ortools/constraint_solver/samples/vrp_items_to_deliver.py index fade08d880..10b0b3dc37 100755 --- a/ortools/constraint_solver/samples/vrp_items_to_deliver.py +++ b/ortools/constraint_solver/samples/vrp_items_to_deliver.py @@ -24,17 +24,17 @@ from ortools.constraint_solver import pywrapcp def create_data_model(): """Stores the data for the problem.""" data = {} - data['num_vehicles'] = 2 + data["num_vehicles"] = 2 # [START starts_ends] - data['starts'] = [0] * data['num_vehicles'] - data['ends'] = [1] * data['num_vehicles'] - assert len(data['starts']) == data['num_vehicles'] - assert len(data['ends']) == data['num_vehicles'] + data["starts"] = [0] * data["num_vehicles"] + data["ends"] = [1] * data["num_vehicles"] + assert len(data["starts"]) == data["num_vehicles"] + assert len(data["ends"]) == data["num_vehicles"] # [END starts_ends] # [START demands_capacities] # Need 11 X and 13 Y - data['providers_x'] = [ + data["providers_x"] = [ 0, # start -11, # end 2, # X supply 1 @@ -53,7 +53,7 @@ def create_data_model(): 0, # Y supply 5 0, # Y supply 6 ] - data['providers_y'] = [ + data["providers_y"] = [ 0, # start -13, # ends 0, # X supply 1 @@ -72,12 +72,12 @@ def create_data_model(): 3, # Y supply 5 5, # Y supply 6 ] - data['vehicle_capacities_x'] = [15] * data['num_vehicles'] - data['vehicle_capacities_y'] = [15] * data['num_vehicles'] - assert len(data['vehicle_capacities_x']) == data['num_vehicles'] - assert len(data['vehicle_capacities_y']) == data['num_vehicles'] + data["vehicle_capacities_x"] = [15] * data["num_vehicles"] + data["vehicle_capacities_y"] = [15] * data["num_vehicles"] + assert len(data["vehicle_capacities_x"]) == data["num_vehicles"] + assert len(data["vehicle_capacities_y"]) == data["num_vehicles"] # [END demands_capacities] - data['distance_matrix'] = [ + data["distance_matrix"] = [ [ 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662 @@ -208,9 +208,9 @@ def main(): # Create the routing index manager. # [START index_manager] - manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']), - data['num_vehicles'], data['starts'], - data['ends']) + manager = pywrapcp.RoutingIndexManager( + len(data["distance_matrix"]), data["num_vehicles"], data["starts"], data["ends"] + ) # [END index_manager] # Create Routing Model. @@ -226,7 +226,7 @@ def main(): # 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] + return data["distance_matrix"][from_node][to_node] transit_callback_index = routing.RegisterTransitCallback(distance_callback) # [END transit_callback] @@ -238,13 +238,14 @@ def main(): # Add Distance constraint. # [START distance_constraint] - dimension_name = 'Distance' + dimension_name = "Distance" routing.AddDimension( transit_callback_index, 0, # no slack 2000, # vehicle maximum travel distance True, # start cumul to zero - dimension_name) + dimension_name, + ) distance_dimension = routing.GetDimensionOrDie(dimension_name) # Minimize the longest road distance_dimension.SetGlobalSpanCostCoefficient(100) @@ -257,65 +258,69 @@ def main(): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) - return data['providers_x'][from_node] + return data["providers_x"][from_node] - demand_callback_x_index = routing.RegisterUnaryTransitCallback( - demand_callback_x) + demand_callback_x_index = routing.RegisterUnaryTransitCallback(demand_callback_x) routing.AddDimensionWithVehicleCapacity( demand_callback_x_index, 0, # null capacity slack - data['vehicle_capacities_x'], # vehicle maximum capacities + data["vehicle_capacities_x"], # vehicle maximum capacities True, # start cumul to zero - 'Load_x') + "Load_x", + ) def demand_callback_y(from_index): """Returns the demand of the node.""" # Convert from routing variable Index to demands NodeIndex. from_node = manager.IndexToNode(from_index) - return data['providers_y'][from_node] + return data["providers_y"][from_node] - demand_callback_y_index = routing.RegisterUnaryTransitCallback( - demand_callback_y) + demand_callback_y_index = routing.RegisterUnaryTransitCallback(demand_callback_y) routing.AddDimensionWithVehicleCapacity( demand_callback_y_index, 0, # null capacity slack - data['vehicle_capacities_y'], # vehicle maximum capacities + data["vehicle_capacities_y"], # vehicle maximum capacities True, # start cumul to zero - 'Load_y') + "Load_y", + ) # [END capacity_constraint] # Add constraint at end solver = routing.solver() - load_x_dim = routing.GetDimensionOrDie('Load_x') - load_y_dim = routing.GetDimensionOrDie('Load_y') + load_x_dim = routing.GetDimensionOrDie("Load_x") + load_y_dim = routing.GetDimensionOrDie("Load_y") ends = [] for v in range(manager.GetNumberOfVehicles()): ends.append(routing.End(v)) - node_end = data['ends'][0] + node_end = data["ends"][0] solver.Add( - solver.Sum([load_x_dim.CumulVar(l) - for l in ends]) >= -data['providers_x'][node_end]) + solver.Sum([load_x_dim.CumulVar(l) for l in ends]) + >= -data["providers_x"][node_end] + ) solver.Add( - solver.Sum([load_y_dim.CumulVar(l) - for l in ends]) >= -data['providers_y'][node_end]) - #solver.Add(load_y_dim.CumulVar(end) >= -data['providers_y'][node_end]) + solver.Sum([load_y_dim.CumulVar(l) for l in ends]) + >= -data["providers_y"][node_end] + ) + # solver.Add(load_y_dim.CumulVar(end) >= -data['providers_y'][node_end]) # Allow to freely drop any nodes. penalty = 0 - for node in range(0, len(data['distance_matrix'])): - if node not in data['starts'] and node not in data['ends']: + for node in range(0, len(data["distance_matrix"])): + if node not in data["starts"] and node not in data["ends"]: routing.AddDisjunction([manager.NodeToIndex(node)], penalty) # Setting first solution heuristic. # [START parameters] search_parameters = pywrapcp.DefaultRoutingSearchParameters() search_parameters.first_solution_strategy = ( - routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) search_parameters.local_search_metaheuristic = ( - routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) # Sets a time limit; default is 100 milliseconds. - #search_parameters.log_search = True + # search_parameters.log_search = True search_parameters.time_limit.FromSeconds(1) # [END parameters] @@ -329,10 +334,10 @@ def main(): if solution: print_solution(data, manager, routing, solution) else: - print('no solution found !') + print("no solution found !") # [END print_solution] -if __name__ == '__main__': +if __name__ == "__main__": main() # [END program] diff --git a/ortools/constraint_solver/samples/vrp_node_max.py b/ortools/constraint_solver/samples/vrp_node_max.py index 336f82e372..17a8e0b91e 100755 --- a/ortools/constraint_solver/samples/vrp_node_max.py +++ b/ortools/constraint_solver/samples/vrp_node_max.py @@ -137,7 +137,6 @@ def main(): # Create Routing Model. # [START routing_model] routing = pywrapcp.RoutingModel(manager) - # [END routing_model] # Create and register a transit callback. diff --git a/ortools/constraint_solver/samples/vrp_nodes_indices.py b/ortools/constraint_solver/samples/vrp_nodes_indices.py index 367b5ea69e..1a66624801 100755 --- a/ortools/constraint_solver/samples/vrp_nodes_indices.py +++ b/ortools/constraint_solver/samples/vrp_nodes_indices.py @@ -51,60 +51,58 @@ def main(): manager = pywrapcp.RoutingIndexManager(locations, vehicles, starts, ends) routing = pywrapcp.RoutingModel(manager) - print('Starts/Ends:') - header = '| |' - separator = '|---|' - v_starts = '| start |' - v_ends = '| end |' + print("Starts/Ends:") + header = "| |" + separator = "|---|" + v_starts = "| start |" + v_ends = "| end |" for v in range(manager.GetNumberOfVehicles()): - header += f' vehicle {v} |' - separator += '---|' - v_starts += f' {starts[v]} |' - v_ends += f' {ends[v]} |' + header += f" vehicle {v} |" + separator += "---|" + v_starts += f" {starts[v]} |" + v_ends += f" {ends[v]} |" print(header) print(separator) print(v_starts) print(v_ends) - print('\nNodes:') + print("\nNodes:") print( - '| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices | routing.nodes | routing.Size |' + "| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices | routing.nodes | routing.Size |" ) - print('|---|---|---|---|---|') + print("|---|---|---|---|---|") print( - f'| {locations} | {manager.GetNumberOfNodes()} | {manager.GetNumberOfIndices()} | {routing.nodes()} | {routing.Size()} |' + f"| {locations} | {manager.GetNumberOfNodes()} | {manager.GetNumberOfIndices()} | {routing.nodes()} | {routing.Size()} |" ) - print('\nLocations:') - print('| node | index | routing.IsStart | routing.IsEnd |') - print('|---|---|---|---|') + print("\nLocations:") + print("| node | index | routing.IsStart | routing.IsEnd |") + print("|---|---|---|---|") for node in range(manager.GetNumberOfNodes()): if node in starts or node in ends: continue index = manager.NodeToIndex(node) print( - f'| {node} | {index} | {routing.IsStart(index)} | {routing.IsEnd(index)} |' + f"| {node} | {index} | {routing.IsStart(index)} | {routing.IsEnd(index)} |" ) - print('\nStart/End:') - print( - '| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |' - ) - print('|---|---|---|---|---|---|') + print("\nStart/End:") + print("| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |") + print("|---|---|---|---|---|---|") for v in range(manager.GetNumberOfVehicles()): start_index = routing.Start(v) start_node = manager.IndexToNode(start_index) print( - f'| {v} | start | {start_node} | {start_index} | {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |' + f"| {v} | start | {start_node} | {start_index} | {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |" ) for v in range(manager.GetNumberOfVehicles()): end_index = routing.End(v) end_node = manager.IndexToNode(end_index) print( - f'| {v} | end | {end_node} | {end_index} | {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |' + f"| {v} | end | {end_node} | {end_index} | {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |" ) -if __name__ == '__main__': +if __name__ == "__main__": main() # [END program] diff --git a/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py b/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py index b117a68be3..1096afaf9b 100755 --- a/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py +++ b/ortools/constraint_solver/samples/vrp_time_windows_per_vehicles.py @@ -39,7 +39,7 @@ from ortools.constraint_solver import pywrapcp def create_data_model(): """Stores the data for the problem.""" data = {} - data['time_matrix'] = [ + data["time_matrix"] = [ [0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7], [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14], [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9], @@ -58,8 +58,8 @@ def create_data_model(): [9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9], [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0], ] - data['num_vehicles'] = 4 - data['depot'] = 0 + data["num_vehicles"] = 4 + data["depot"] = 0 return data # [END data_model] @@ -67,9 +67,9 @@ def create_data_model(): # [START solution_printer] def print_solution(manager, routing, assignment): """Prints solution on console.""" - print(f'Objective: {assignment.ObjectiveValue()}') + print(f"Objective: {assignment.ObjectiveValue()}") # Display dropped nodes. - dropped_nodes = 'Dropped nodes:' + dropped_nodes = "Dropped nodes:" for index in range(routing.Size()): if routing.IsStart(index) or routing.IsEnd(index): continue @@ -79,15 +79,15 @@ def print_solution(manager, routing, assignment): original = node while original > 16: original = original - 16 - dropped_nodes += f' {node}({original})' + dropped_nodes += f" {node}({original})" else: - dropped_nodes += f' {node}' + dropped_nodes += f" {node}" print(dropped_nodes) # Display routes - time_dimension = routing.GetDimensionOrDie('Time') + time_dimension = routing.GetDimensionOrDie("Time") total_time = 0 for vehicle_id in range(manager.GetNumberOfVehicles()): - plan_output = f'Route for vehicle {vehicle_id}:\n' + plan_output = f"Route for vehicle {vehicle_id}:\n" index = routing.Start(vehicle_id) start_time = 0 while not routing.IsEnd(index): @@ -97,22 +97,22 @@ def print_solution(manager, routing, assignment): original = node while original > 16: original = original - 16 - plan_output += f'{node}({original})' + plan_output += f"{node}({original})" else: - plan_output += f'{node}' - plan_output += f' Time:{assignment.Value(time_var)} -> ' + plan_output += f"{node}" + plan_output += f" Time:{assignment.Value(time_var)} -> " if start_time == 0: start_time = assignment.Value(time_var) index = assignment.Value(routing.NextVar(index)) time_var = time_dimension.CumulVar(index) node = manager.IndexToNode(index) - plan_output += f'{node} Time:{assignment.Value(time_var)}\n' + plan_output += f"{node} Time:{assignment.Value(time_var)}\n" end_time = assignment.Value(time_var) duration = end_time - start_time - plan_output += f'Duration of the route:{duration}min\n' + plan_output += f"Duration of the route:{duration}min\n" print(plan_output) total_time += duration - print(f'Total duration of all routes: {total_time}min') + print(f"Total duration of all routes: {total_time}min") # [END solution_printer] @@ -126,9 +126,8 @@ def main(): # Create the routing index manager. # [START index_manager] manager = pywrapcp.RoutingIndexManager( - 1 + 16 * 4, # number of locations - data['num_vehicles'], - data['depot']) + 1 + 16 * 4, data["num_vehicles"], data["depot"] # number of locations + ) # [END index_manager] # Create Routing Model. @@ -152,9 +151,9 @@ def main(): to_node = to_node - 16 # add service of 25min for each location (except depot) service_time = 0 - if from_node != data['depot']: + if from_node != data["depot"]: service_time = 25 - return data['time_matrix'][from_node][to_node] + service_time + return data["time_matrix"][from_node][to_node] + service_time transit_callback_index = routing.RegisterTransitCallback(time_callback) # [END transit_callback] @@ -166,17 +165,18 @@ def main(): # Add Time Windows constraint. # [START time_windows_constraint] - time = 'Time' + time = "Time" routing.AddDimension( transit_callback_index, 0, # allow waiting time (0 min) 1020, # maximum time per vehicle (9 hours) False, # Don't force start cumul to zero. - time) + time, + ) time_dimension = routing.GetDimensionOrDie(time) # Add time window constraints for each location except depot. for location_idx in range(17): - if location_idx == data['depot']: + if location_idx == data["depot"]: continue # Vehicle 0 location TW: [9am, 11am] index_0 = manager.NodeToIndex(location_idx) @@ -203,34 +203,36 @@ def main(): routing.AddDisjunction([index_0, index_1, index_2, index_3], penalty, 1) # Add time window constraints for each vehicle start node. - depot_idx = data['depot'] - for vehicle_id in range(data['num_vehicles']): + depot_idx = data["depot"] + for vehicle_id in range(data["num_vehicles"]): index = routing.Start(vehicle_id) time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm) # Add time window constraints for each vehicle end node. - depot_idx = data['depot'] - for vehicle_id in range(data['num_vehicles']): + depot_idx = data["depot"] + for vehicle_id in range(data["num_vehicles"]): index = routing.End(vehicle_id) time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm) # [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']): + for i in range(data["num_vehicles"]): routing.AddVariableMinimizedByFinalizer( - time_dimension.CumulVar(routing.Start(i))) - routing.AddVariableMinimizedByFinalizer( - time_dimension.CumulVar(routing.End(i))) + 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) + routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC + ) search_parameters.local_search_metaheuristic = ( - routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH) + routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH + ) search_parameters.time_limit.FromSeconds(1) # [END parameters] @@ -248,6 +250,6 @@ def main(): # [END print_solution] -if __name__ == '__main__': +if __name__ == "__main__": main() # [END program] diff --git a/ortools/linear_solver/python/linear_solver_natural_api.py b/ortools/linear_solver/python/linear_solver_natural_api.py index f869e8e9e3..1332b79ac9 100644 --- a/ortools/linear_solver/python/linear_solver_natural_api.py +++ b/ortools/linear_solver/python/linear_solver_natural_api.py @@ -208,6 +208,7 @@ class ProductCst(LinearExpr): class Constant(LinearExpr): + def __init__(self, val): self.__val = val diff --git a/ortools/linear_solver/python/lp_api_test.py b/ortools/linear_solver/python/lp_api_test.py index 5701145d5a..6f2879e4ff 100755 --- a/ortools/linear_solver/python/lp_api_test.py +++ b/ortools/linear_solver/python/lp_api_test.py @@ -7,18 +7,18 @@ import types def Sum(arg): - if type(arg) is types.GeneratorType: - arg = [x for x in arg] - sum = 0 - for i in arg: - sum += i - print('sum(%s) = %d' % (str(arg), sum)) - + if type(arg) is types.GeneratorType: + arg = [x for x in arg] + sum = 0 + for i in arg: + sum += i + print("sum(%s) = %d" % (str(arg), sum)) def test_sum_no_brackets(): - Sum(x for x in range(10) if x % 2 == 0) - Sum([x for x in range(10) if x % 2 == 0]) + Sum(x for x in range(10) if x % 2 == 0) + Sum([x for x in range(10) if x % 2 == 0]) + text_model = """ solver_type:GLOP_LINEAR_PROGRAMMING @@ -37,24 +37,24 @@ model < def test_proto(): - input_proto = linear_solver_pb2.MPModelRequest() - text_format.Merge(text_model, input_proto) - solver = pywraplp.Solver.CreateSolver('glop') - print(input_proto) - # For now, create the model from the proto by parsing the proto - solver.LoadModelFromProto(input_proto.model) - solver.EnableOutput() - solver.Solve() - # Fill solution - solution = linear_solver_pb2.MPSolutionResponse() - solver.FillSolutionResponseProto(solution) - print(solution) + input_proto = linear_solver_pb2.MPModelRequest() + text_format.Merge(text_model, input_proto) + solver = pywraplp.Solver.CreateSolver("glop") + print(input_proto) + # For now, create the model from the proto by parsing the proto + solver.LoadModelFromProto(input_proto.model) + solver.EnableOutput() + solver.Solve() + # Fill solution + solution = linear_solver_pb2.MPSolutionResponse() + solver.FillSolutionResponseProto(solution) + print(solution) def main(): - test_sum_no_brackets() - test_proto() + test_sum_no_brackets() + test_proto() -if __name__ == '__main__': - main() +if __name__ == "__main__": + main() diff --git a/ortools/linear_solver/python/lp_test.py b/ortools/linear_solver/python/lp_test.py index 383a1604ec..a52dc3467b 100755 --- a/ortools/linear_solver/python/lp_test.py +++ b/ortools/linear_solver/python/lp_test.py @@ -22,36 +22,39 @@ from ortools.linear_solver import pywraplp class PyWrapLpTest(unittest.TestCase): def RunLinearExampleNaturalLanguageAPI(self, optimization_problem_type): """Example of simple linear program with natural language API.""" - solver = pywraplp.Solver('RunLinearExampleNaturalLanguageAPI', - optimization_problem_type) + solver = pywraplp.Solver( + "RunLinearExampleNaturalLanguageAPI", optimization_problem_type + ) infinity = solver.infinity() # x1, x2 and x3 are continuous non-negative variables. - x1 = solver.NumVar(0.0, infinity, 'x1') - x2 = solver.NumVar(0.0, infinity, 'x2') - x3 = solver.NumVar(0.0, infinity, 'x3') + x1 = solver.NumVar(0.0, infinity, "x1") + x2 = solver.NumVar(0.0, infinity, "x2") + x3 = solver.NumVar(0.0, infinity, "x3") solver.Maximize(10 * x1 + 6 * x2 + 4 * x3) - c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, 'ConstraintName0') + c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, "ConstraintName0") c1 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300) sum_of_vars = sum([x1, x2, x3]) - c2 = solver.Add(sum_of_vars <= 100.0, 'OtherConstraintName') + c2 = solver.Add(sum_of_vars <= 100.0, "OtherConstraintName") - self.SolveAndPrint(solver, [x1, x2, x3], [c0, c1, c2], - optimization_problem_type != pywraplp.Solver.PDLP_LINEAR_PROGRAMMING) + self.SolveAndPrint( + solver, + [x1, x2, x3], + [c0, c1, c2], + optimization_problem_type != pywraplp.Solver.PDLP_LINEAR_PROGRAMMING, + ) # Print a linear expression's solution value. - print(('Sum of vars: %s = %s' % (sum_of_vars, - sum_of_vars.solution_value()))) + print(("Sum of vars: %s = %s" % (sum_of_vars, sum_of_vars.solution_value()))) def RunLinearExampleCppStyleAPI(self, optimization_problem_type): """Example of simple linear program with the C++ style API.""" - solver = pywraplp.Solver('RunLinearExampleCppStyle', - optimization_problem_type) + solver = pywraplp.Solver("RunLinearExampleCppStyle", optimization_problem_type) infinity = solver.infinity() # x1, x2 and x3 are continuous non-negative variables. - x1 = solver.NumVar(0.0, infinity, 'x1') - x2 = solver.NumVar(0.0, infinity, 'x2') - x3 = solver.NumVar(0.0, infinity, 'x3') + x1 = solver.NumVar(0.0, infinity, "x1") + x2 = solver.NumVar(0.0, infinity, "x2") + x3 = solver.NumVar(0.0, infinity, "x3") # Maximize 10 * x1 + 6 * x2 + 4 * x3. objective = solver.Objective() @@ -61,34 +64,39 @@ class PyWrapLpTest(unittest.TestCase): objective.SetMaximization() # x1 + x2 + x3 <= 100. - c0 = solver.Constraint(-infinity, 100.0, 'c0') + c0 = solver.Constraint(-infinity, 100.0, "c0") c0.SetCoefficient(x1, 1) c0.SetCoefficient(x2, 1) c0.SetCoefficient(x3, 1) # 10 * x1 + 4 * x2 + 5 * x3 <= 600. - c1 = solver.Constraint(-infinity, 600.0, 'c1') + c1 = solver.Constraint(-infinity, 600.0, "c1") c1.SetCoefficient(x1, 10) c1.SetCoefficient(x2, 4) c1.SetCoefficient(x3, 5) # 2 * x1 + 2 * x2 + 6 * x3 <= 300. - c2 = solver.Constraint(-infinity, 300.0, 'c2') + c2 = solver.Constraint(-infinity, 300.0, "c2") c2.SetCoefficient(x1, 2) c2.SetCoefficient(x2, 2) c2.SetCoefficient(x3, 6) - self.SolveAndPrint(solver, [x1, x2, x3], [c0, c1, c2], - optimization_problem_type != pywraplp.Solver.PDLP_LINEAR_PROGRAMMING) + self.SolveAndPrint( + solver, + [x1, x2, x3], + [c0, c1, c2], + optimization_problem_type != pywraplp.Solver.PDLP_LINEAR_PROGRAMMING, + ) def RunMixedIntegerExampleCppStyleAPI(self, optimization_problem_type): """Example of simple mixed integer program with the C++ style API.""" - solver = pywraplp.Solver('RunMixedIntegerExampleCppStyle', - optimization_problem_type) + solver = pywraplp.Solver( + "RunMixedIntegerExampleCppStyle", optimization_problem_type + ) infinity = solver.infinity() # x1 and x2 are integer non-negative variables. - x1 = solver.IntVar(0.0, infinity, 'x1') - x2 = solver.IntVar(0.0, infinity, 'x2') + x1 = solver.IntVar(0.0, infinity, "x1") + x2 = solver.IntVar(0.0, infinity, "x2") # Maximize x1 + 10 * x2. objective = solver.Objective() @@ -97,12 +105,12 @@ class PyWrapLpTest(unittest.TestCase): objective.SetMaximization() # x1 + 7 * x2 <= 17.5. - c0 = solver.Constraint(-infinity, 17.5, 'c0') + c0 = solver.Constraint(-infinity, 17.5, "c0") c0.SetCoefficient(x1, 1) c0.SetCoefficient(x2, 7) # x1 <= 3.5. - c1 = solver.Constraint(-infinity, 3.5, 'c1') + c1 = solver.Constraint(-infinity, 3.5, "c1") c1.SetCoefficient(x1, 1) c1.SetCoefficient(x2, 0) @@ -110,11 +118,10 @@ class PyWrapLpTest(unittest.TestCase): def RunBooleanExampleCppStyleAPI(self, optimization_problem_type): """Example of simple boolean program with the C++ style API.""" - solver = pywraplp.Solver('RunBooleanExampleCppStyle', - optimization_problem_type) + solver = pywraplp.Solver("RunBooleanExampleCppStyle", optimization_problem_type) # x1 and x2 are integer non-negative variables. - x1 = solver.BoolVar('x1') - x2 = solver.BoolVar('x2') + x1 = solver.BoolVar("x1") + x2 = solver.BoolVar("x2") # Minimize 2 * x1 + x2. objective = solver.Objective() @@ -123,7 +130,7 @@ class PyWrapLpTest(unittest.TestCase): objective.SetMinimization() # 1 <= x1 + 2 * x2 <= 3. - c0 = solver.Constraint(1, 3, 'c0') + c0 = solver.Constraint(1, 3, "c0") c0.SetCoefficient(x1, 1) c0.SetCoefficient(x2, 2) @@ -131,10 +138,10 @@ class PyWrapLpTest(unittest.TestCase): def SolveAndPrint(self, solver, variable_list, constraint_list, is_precise): """Solve the problem and print the solution.""" - print(('Number of variables = %d' % solver.NumVariables())) + print(("Number of variables = %d" % solver.NumVariables())) self.assertEqual(solver.NumVariables(), len(variable_list)) - print(('Number of constraints = %d' % solver.NumConstraints())) + print(("Number of constraints = %d" % solver.NumConstraints())) self.assertEqual(solver.NumConstraints(), len(constraint_list)) result_status = solver.Solve() @@ -147,72 +154,84 @@ class PyWrapLpTest(unittest.TestCase): if is_precise: self.assertTrue(solver.VerifySolution(1e-7, True)) - print(('Problem solved in %f milliseconds' % solver.wall_time())) + print(("Problem solved in %f milliseconds" % solver.wall_time())) # The objective value of the solution. - print(('Optimal objective value = %f' % solver.Objective().Value())) + print(("Optimal objective value = %f" % solver.Objective().Value())) # The value of each variable in the solution. for variable in variable_list: - print(('%s = %f' % (variable.name(), variable.solution_value()))) + print(("%s = %f" % (variable.name(), variable.solution_value()))) - print('Advanced usage:') - print(('Problem solved in %d iterations' % solver.iterations())) + print("Advanced usage:") + print(("Problem solved in %d iterations" % solver.iterations())) if not solver.IsMip(): for variable in variable_list: - print(('%s: reduced cost = %f' % (variable.name(), - variable.reduced_cost()))) + print( + ( + "%s: reduced cost = %f" + % (variable.name(), variable.reduced_cost()) + ) + ) activities = solver.ComputeConstraintActivities() for i, constraint in enumerate(constraint_list): print( - ('constraint %d: dual value = %f\n' - ' activity = %f' % - (i, constraint.dual_value(), activities[constraint.index()]))) + ( + "constraint %d: dual value = %f\n" + " activity = %f" + % (i, constraint.dual_value(), activities[constraint.index()]) + ) + ) def testApi(self): - print('testApi', flush=True) - all_names_and_problem_types = (list( - linear_solver_pb2.MPModelRequest.SolverType.items())) + print("testApi", flush=True) + all_names_and_problem_types = list( + linear_solver_pb2.MPModelRequest.SolverType.items() + ) for name, problem_type in all_names_and_problem_types: - with self.subTest(f'{name}: {problem_type}'): - print(f'######## {name}:{problem_type} #######', flush=True) + with self.subTest(f"{name}: {problem_type}"): + print(f"######## {name}:{problem_type} #######", flush=True) if not pywraplp.Solver.SupportsProblemType(problem_type): continue - if name.startswith('GUROBI'): + if name.startswith("GUROBI"): continue - if name.startswith('KNAPSACK'): + if name.startswith("KNAPSACK"): continue - if not name.startswith('SCIP'): + if not name.startswith("SCIP"): continue - if name.endswith('LINEAR_PROGRAMMING'): - print(('\n------ Linear programming example with %s ------' % - name)) - print('\n*** Natural language API ***') + if name.endswith("LINEAR_PROGRAMMING"): + print(("\n------ Linear programming example with %s ------" % name)) + print("\n*** Natural language API ***") self.RunLinearExampleNaturalLanguageAPI(problem_type) - print('\n*** C++ style API ***') + print("\n*** C++ style API ***") self.RunLinearExampleCppStyleAPI(problem_type) - elif name.endswith('MIXED_INTEGER_PROGRAMMING'): - print(( - '\n------ Mixed Integer programming example with %s ------' - % name)) - print('\n*** C++ style API ***') + elif name.endswith("MIXED_INTEGER_PROGRAMMING"): + print( + ( + "\n------ Mixed Integer programming example with %s ------" + % name + ) + ) + print("\n*** C++ style API ***") self.RunMixedIntegerExampleCppStyleAPI(problem_type) - elif name.endswith('INTEGER_PROGRAMMING'): - print(('\n------ Boolean programming example with %s ------' % - name)) - print('\n*** C++ style API ***') + elif name.endswith("INTEGER_PROGRAMMING"): + print( + ("\n------ Boolean programming example with %s ------" % name) + ) + print("\n*** C++ style API ***") self.RunBooleanExampleCppStyleAPI(problem_type) else: - print('ERROR: %s unsupported' % name) + print("ERROR: %s unsupported" % name) def testSetHint(self): - print('testSetHint', flush=True) - solver = pywraplp.Solver('RunBooleanExampleCppStyle', - pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) + print("testSetHint", flush=True) + solver = pywraplp.Solver( + "RunBooleanExampleCppStyle", pywraplp.Solver.GLOP_LINEAR_PROGRAMMING + ) infinity = solver.infinity() # x1 and x2 are integer non-negative variables. - x1 = solver.BoolVar('x1') - x2 = solver.BoolVar('x2') + x1 = solver.BoolVar("x1") + x2 = solver.BoolVar("x2") # Minimize 2 * x1 + x2. objective = solver.Objective() @@ -221,7 +240,7 @@ class PyWrapLpTest(unittest.TestCase): objective.SetMinimization() # 1 <= x1 + 2 * x2 <= 3. - c0 = solver.Constraint(1, 3, 'c0') + c0 = solver.Constraint(1, 3, "c0") c0.SetCoefficient(x1, 1) c0.SetCoefficient(x2, 2) @@ -230,24 +249,24 @@ class PyWrapLpTest(unittest.TestCase): self.assertEqual(1, len(solver.constraints())) def testBopInfeasible(self): - print('testBopInfeasible', flush=True) - solver = pywraplp.Solver('test', pywraplp.Solver.BOP_INTEGER_PROGRAMMING) + print("testBopInfeasible", flush=True) + solver = pywraplp.Solver("test", pywraplp.Solver.BOP_INTEGER_PROGRAMMING) solver.EnableOutput() x = solver.IntVar(0, 10, "") solver.Add(x >= 20) result_status = solver.Solve() - print(result_status) # outputs: 0 + print(result_status) # outputs: 0 def testLoadSolutionFromProto(self): - print('testLoadSolutionFromProto', flush=True) - solver = pywraplp.Solver('', pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) + print("testLoadSolutionFromProto", flush=True) + solver = pywraplp.Solver("", pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) solver.LoadSolutionFromProto(linear_solver_pb2.MPSolutionResponse()) def testSolveFromProto(self): - print('testSolveFromProto', flush=True) - request_str = ''' + print("testSolveFromProto", flush=True) + request_str = """ model { maximize: false objective_offset: 0 @@ -304,36 +323,35 @@ class PyWrapLpTest(unittest.TestCase): solver_type: GLOP_LINEAR_PROGRAMMING solver_time_limit_seconds: 1.0 solver_specific_parameters: "" - ''' + """ request = linear_solver_pb2.MPModelRequest() text_format.Parse(request_str, request) response = linear_solver_pb2.MPSolutionResponse() self.assertEqual(len(request.model.variable), 3) pywraplp.Solver.SolveWithProto(model_request=request, response=response) self.assertEqual( - linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL, - response.status) + linear_solver_pb2.MPSolverResponseStatus.MPSOLVER_OPTIMAL, response.status + ) def testExportToMps(self): """Test MPS export.""" - print('testExportToMps', flush=True) - solver = pywraplp.Solver('ExportMps', - pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) + print("testExportToMps", flush=True) + solver = pywraplp.Solver("ExportMps", pywraplp.Solver.GLOP_LINEAR_PROGRAMMING) infinity = solver.infinity() # x1, x2 and x3 are continuous non-negative variables. - x1 = solver.NumVar(0.0, infinity, 'x1') - x2 = solver.NumVar(0.0, infinity, 'x2') - x3 = solver.NumVar(0.0, infinity, 'x3') + x1 = solver.NumVar(0.0, infinity, "x1") + x2 = solver.NumVar(0.0, infinity, "x2") + x3 = solver.NumVar(0.0, infinity, "x3") solver.Maximize(10 * x1 + 6 * x2 + 4 * x3) - c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, 'ConstraintName0') + c0 = solver.Add(10 * x1 + 4 * x2 + 5 * x3 <= 600, "ConstraintName0") c1 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300) sum_of_vars = sum([x1, x2, x3]) - c2 = solver.Add(sum_of_vars <= 100.0, 'OtherConstraintName') + c2 = solver.Add(sum_of_vars <= 100.0, "OtherConstraintName") mps_str = solver.ExportModelAsMpsFormat(fixed_format=False, obfuscated=False) - self.assertIn('ExportMps', mps_str) + self.assertIn("ExportMps", mps_str) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/ortools/math_opt/python/compute_infeasible_subsystem_result.py b/ortools/math_opt/python/compute_infeasible_subsystem_result.py index 4f981cfba7..7f66dc43ab 100644 --- a/ortools/math_opt/python/compute_infeasible_subsystem_result.py +++ b/ortools/math_opt/python/compute_infeasible_subsystem_result.py @@ -72,13 +72,13 @@ class ModelSubset: constraints are included in the subset. """ - variable_bounds: Mapping[ - model.Variable, ModelSubsetBounds - ] = immutabledict.immutabledict() + variable_bounds: Mapping[model.Variable, ModelSubsetBounds] = ( + immutabledict.immutabledict() + ) variable_integrality: FrozenSet[model.Variable] = frozenset() - linear_constraints: Mapping[ - model.LinearConstraint, ModelSubsetBounds - ] = immutabledict.immutabledict() + linear_constraints: Mapping[model.LinearConstraint, ModelSubsetBounds] = ( + immutabledict.immutabledict() + ) def empty(self) -> bool: """Returns true if all the nested constraint collections are empty. diff --git a/ortools/math_opt/python/expressions.py b/ortools/math_opt/python/expressions.py index fb1fb02f6c..36cd5cc6cd 100644 --- a/ortools/math_opt/python/expressions.py +++ b/ortools/math_opt/python/expressions.py @@ -20,15 +20,13 @@ from ortools.math_opt.python import model @typing.overload -def fast_sum(summands: Iterable[model.LinearTypes]) -> model.LinearSum: - ... +def fast_sum(summands: Iterable[model.LinearTypes]) -> model.LinearSum: ... @typing.overload def fast_sum( summands: Iterable[model.QuadraticTypes], -) -> Union[model.LinearSum, model.QuadraticSum]: - ... +) -> Union[model.LinearSum, model.QuadraticSum]: ... # TODO(b/312200030): There is a pytype bug so that for the code: diff --git a/ortools/math_opt/python/hash_model_storage.py b/ortools/math_opt/python/hash_model_storage.py index c33bdf4091..5dda863be9 100644 --- a/ortools/math_opt/python/hash_model_storage.py +++ b/ortools/math_opt/python/hash_model_storage.py @@ -180,12 +180,12 @@ class _UpdateTracker(model_storage.StorageUpdateTracker): *quadratic_objective_updates ) result.objective_updates.quadratic_coefficients.row_ids[:] = first_var_ids - result.objective_updates.quadratic_coefficients.column_ids[ - : - ] = second_var_ids - result.objective_updates.quadratic_coefficients.coefficients[ - : - ] = coefficients + result.objective_updates.quadratic_coefficients.column_ids[:] = ( + second_var_ids + ) + result.objective_updates.quadratic_coefficients.coefficients[:] = ( + coefficients + ) # Linear constraint matrix updates matrix_updates = [ (l, v, self.model.get_linear_constraint_coefficient(l, v)) diff --git a/ortools/math_opt/python/model.py b/ortools/math_opt/python/model.py index 7156c46975..e979bbcde8 100644 --- a/ortools/math_opt/python/model.py +++ b/ortools/math_opt/python/model.py @@ -481,16 +481,13 @@ class LinearBase(metaclass=abc.ABCMeta): _raise_ne_not_supported() @typing.overload - def __le__(self, rhs: float) -> "UpperBoundedLinearExpression": - ... + def __le__(self, rhs: float) -> "UpperBoundedLinearExpression": ... @typing.overload - def __le__(self, rhs: "LinearBase") -> "BoundedLinearExpression": - ... + def __le__(self, rhs: "LinearBase") -> "BoundedLinearExpression": ... @typing.overload - def __le__(self, rhs: "BoundedLinearExpression") -> NoReturn: - ... + def __le__(self, rhs: "BoundedLinearExpression") -> NoReturn: ... def __le__(self, rhs): if isinstance(rhs, (int, float)): @@ -504,16 +501,13 @@ class LinearBase(metaclass=abc.ABCMeta): _raise_binary_operator_type_error("<=", type(self), type(rhs)) @typing.overload - def __ge__(self, lhs: float) -> "LowerBoundedLinearExpression": - ... + def __ge__(self, lhs: float) -> "LowerBoundedLinearExpression": ... @typing.overload - def __ge__(self, lhs: "LinearBase") -> "BoundedLinearExpression": - ... + def __ge__(self, lhs: "LinearBase") -> "BoundedLinearExpression": ... @typing.overload - def __ge__(self, lhs: "BoundedLinearExpression") -> NoReturn: - ... + def __ge__(self, lhs: "BoundedLinearExpression") -> NoReturn: ... def __ge__(self, lhs): if isinstance(lhs, (int, float)): @@ -547,12 +541,10 @@ class LinearBase(metaclass=abc.ABCMeta): return LinearSum((expr, -self)) @typing.overload - def __mul__(self, other: float) -> "LinearProduct": - ... + def __mul__(self, other: float) -> "LinearProduct": ... @typing.overload - def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": - ... + def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": ... def __mul__(self, other): if not isinstance(other, (int, float, LinearBase)): @@ -764,12 +756,10 @@ class Variable(LinearBase): return f"" @typing.overload - def __eq__(self, rhs: "Variable") -> "VarEqVar": - ... + def __eq__(self, rhs: "Variable") -> "VarEqVar": ... @typing.overload - def __eq__(self, rhs: LinearTypesExceptVariable) -> "BoundedLinearExpression": - ... + def __eq__(self, rhs: LinearTypesExceptVariable) -> "BoundedLinearExpression": ... def __eq__(self, rhs): if isinstance(rhs, Variable): @@ -777,12 +767,10 @@ class Variable(LinearBase): return super().__eq__(rhs) @typing.overload - def __ne__(self, rhs: "Variable") -> bool: - ... + def __ne__(self, rhs: "Variable") -> bool: ... @typing.overload - def __ne__(self, rhs: LinearTypesExceptVariable) -> NoReturn: - ... + def __ne__(self, rhs: LinearTypesExceptVariable) -> NoReturn: ... def __ne__(self, rhs): if isinstance(rhs, Variable): @@ -793,16 +781,13 @@ class Variable(LinearBase): return hash((self.model, self.id)) @typing.overload - def __mul__(self, other: float) -> "LinearTerm": - ... + def __mul__(self, other: float) -> "LinearTerm": ... @typing.overload - def __mul__(self, other: Union["Variable", "LinearTerm"]) -> "QuadraticTerm": - ... + def __mul__(self, other: Union["Variable", "LinearTerm"]) -> "QuadraticTerm": ... @typing.overload - def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": - ... + def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": ... def __mul__(self, other): if not isinstance(other, (int, float, LinearBase)): @@ -869,16 +854,13 @@ class LinearTerm(LinearBase): processed_elements.terms[self._variable] += self._coefficient * scale @typing.overload - def __mul__(self, other: float) -> "LinearTerm": - ... + def __mul__(self, other: float) -> "LinearTerm": ... @typing.overload - def __mul__(self, other: Union["Variable", "LinearTerm"]) -> "QuadraticTerm": - ... + def __mul__(self, other: Union["Variable", "LinearTerm"]) -> "QuadraticTerm": ... @typing.overload - def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": - ... + def __mul__(self, other: "LinearBase") -> "LinearLinearProduct": ... def __mul__(self, other): if not isinstance(other, (int, float, LinearBase)): @@ -1080,9 +1062,9 @@ class QuadraticExpression(QuadraticBase): if isinstance(other, (int, float)): self._offset = float(other) self._linear_terms: Mapping[Variable, float] = immutabledict.immutabledict() - self._quadratic_terms: Mapping[ - QuadraticTermKey, float - ] = immutabledict.immutabledict() + self._quadratic_terms: Mapping[QuadraticTermKey, float] = ( + immutabledict.immutabledict() + ) return to_process: _QuadraticToProcessElements = _QuadraticToProcessElements( @@ -1103,9 +1085,9 @@ class QuadraticExpression(QuadraticBase): self._linear_terms: Mapping[Variable, float] = immutabledict.immutabledict( processed_elements.terms ) - self._quadratic_terms: Mapping[ - QuadraticTermKey, float - ] = immutabledict.immutabledict(processed_elements.quadratic_terms) + self._quadratic_terms: Mapping[QuadraticTermKey, float] = ( + immutabledict.immutabledict(processed_elements.quadratic_terms) + ) self._offset = processed_elements.offset @property @@ -1563,9 +1545,9 @@ class Model: # detection). Do not access a variable or constraint from these maps # directly, as they may no longer exist, use _get_or_make_variable() and # _get_or_make_linear_constraint() defined below instead. - self._variable_ids: weakref.WeakValueDictionary[ - int, Variable - ] = weakref.WeakValueDictionary() + self._variable_ids: weakref.WeakValueDictionary[int, Variable] = ( + weakref.WeakValueDictionary() + ) self._linear_constraint_ids: weakref.WeakValueDictionary[ int, LinearConstraint ] = weakref.WeakValueDictionary() diff --git a/ortools/math_opt/python/result.py b/ortools/math_opt/python/result.py index 27c4a9b1a2..27988da834 100644 --- a/ortools/math_opt/python/result.py +++ b/ortools/math_opt/python/result.py @@ -483,16 +483,13 @@ class SolveResult: return self.termination.objective_bounds.dual_bound @overload - def variable_values(self, variables: None = ...) -> Dict[model.Variable, float]: - ... + def variable_values(self, variables: None = ...) -> Dict[model.Variable, float]: ... @overload - def variable_values(self, variables: model.Variable) -> float: - ... + def variable_values(self, variables: model.Variable) -> float: ... @overload - def variable_values(self, variables: Iterable[model.Variable]) -> List[float]: - ... + def variable_values(self, variables: Iterable[model.Variable]) -> List[float]: ... def variable_values(self, variables=None): """The variable values from the best primal feasible solution. @@ -549,16 +546,17 @@ class SolveResult: return bool(self.primal_rays) @overload - def ray_variable_values(self, variables: None = ...) -> Dict[model.Variable, float]: - ... + def ray_variable_values( + self, variables: None = ... + ) -> Dict[model.Variable, float]: ... @overload - def ray_variable_values(self, variables: model.Variable) -> float: - ... + def ray_variable_values(self, variables: model.Variable) -> float: ... @overload - def ray_variable_values(self, variables: Iterable[model.Variable]) -> List[float]: - ... + def ray_variable_values( + self, variables: Iterable[model.Variable] + ) -> List[float]: ... def ray_variable_values(self, variables=None): """The variable values from the first primal ray. @@ -613,18 +611,15 @@ class SolveResult: @overload def dual_values( self, linear_constraints: None = ... - ) -> Dict[model.LinearConstraint, float]: - ... + ) -> Dict[model.LinearConstraint, float]: ... @overload - def dual_values(self, linear_constraints: model.LinearConstraint) -> float: - ... + def dual_values(self, linear_constraints: model.LinearConstraint) -> float: ... @overload def dual_values( self, linear_constraints: Iterable[model.LinearConstraint] - ) -> List[float]: - ... + ) -> List[float]: ... def dual_values(self, linear_constraints=None): """The dual values associated to the best solution. @@ -670,16 +665,13 @@ class SolveResult: ) @overload - def reduced_costs(self, variables: None = ...) -> Dict[model.Variable, float]: - ... + def reduced_costs(self, variables: None = ...) -> Dict[model.Variable, float]: ... @overload - def reduced_costs(self, variables: model.Variable) -> float: - ... + def reduced_costs(self, variables: model.Variable) -> float: ... @overload - def reduced_costs(self, variables: Iterable[model.Variable]) -> List[float]: - ... + def reduced_costs(self, variables: Iterable[model.Variable]) -> List[float]: ... def reduced_costs(self, variables=None): """The reduced costs associated to the best solution. @@ -732,18 +724,15 @@ class SolveResult: @overload def ray_dual_values( self, linear_constraints: None = ... - ) -> Dict[model.LinearConstraint, float]: - ... + ) -> Dict[model.LinearConstraint, float]: ... @overload - def ray_dual_values(self, linear_constraints: model.LinearConstraint) -> float: - ... + def ray_dual_values(self, linear_constraints: model.LinearConstraint) -> float: ... @overload def ray_dual_values( self, linear_constraints: Iterable[model.LinearConstraint] - ) -> List[float]: - ... + ) -> List[float]: ... def ray_dual_values(self, linear_constraints=None): """The dual values from the first dual ray. @@ -781,16 +770,15 @@ class SolveResult: ) @overload - def ray_reduced_costs(self, variables: None = ...) -> Dict[model.Variable, float]: - ... + def ray_reduced_costs( + self, variables: None = ... + ) -> Dict[model.Variable, float]: ... @overload - def ray_reduced_costs(self, variables: model.Variable) -> float: - ... + def ray_reduced_costs(self, variables: model.Variable) -> float: ... @overload - def ray_reduced_costs(self, variables: Iterable[model.Variable]) -> List[float]: - ... + def ray_reduced_costs(self, variables: Iterable[model.Variable]) -> List[float]: ... def ray_reduced_costs(self, variables=None): """The reduced costs from the first dual ray. @@ -841,20 +829,17 @@ class SolveResult: @overload def constraint_status( self, linear_constraints: None = ... - ) -> Dict[model.LinearConstraint, solution.BasisStatus]: - ... + ) -> Dict[model.LinearConstraint, solution.BasisStatus]: ... @overload def constraint_status( self, linear_constraints: model.LinearConstraint - ) -> solution.BasisStatus: - ... + ) -> solution.BasisStatus: ... @overload def constraint_status( self, linear_constraints: Iterable[model.LinearConstraint] - ) -> List[solution.BasisStatus]: - ... + ) -> List[solution.BasisStatus]: ... def constraint_status(self, linear_constraints=None): """The constraint basis status associated to the best solution. @@ -900,18 +885,15 @@ class SolveResult: @overload def variable_status( self, variables: None = ... - ) -> Dict[model.Variable, solution.BasisStatus]: - ... + ) -> Dict[model.Variable, solution.BasisStatus]: ... @overload - def variable_status(self, variables: model.Variable) -> solution.BasisStatus: - ... + def variable_status(self, variables: model.Variable) -> solution.BasisStatus: ... @overload def variable_status( self, variables: Iterable[model.Variable] - ) -> List[solution.BasisStatus]: - ... + ) -> List[solution.BasisStatus]: ... def variable_status(self, variables=None): """The variable basis status associated to the best solution. diff --git a/ortools/math_opt/python/solution.py b/ortools/math_opt/python/solution.py index 2e93b53f57..a75cffc131 100644 --- a/ortools/math_opt/python/solution.py +++ b/ortools/math_opt/python/solution.py @@ -390,12 +390,16 @@ class Solution: def to_proto(self) -> solution_pb2.SolutionProto: """Returns an equivalent proto for a solution.""" return solution_pb2.SolutionProto( - primal_solution=self.primal_solution.to_proto() - if self.primal_solution is not None - else None, - dual_solution=self.dual_solution.to_proto() - if self.dual_solution is not None - else None, + primal_solution=( + self.primal_solution.to_proto() + if self.primal_solution is not None + else None + ), + dual_solution=( + self.dual_solution.to_proto() + if self.dual_solution is not None + else None + ), basis=self.basis.to_proto() if self.basis is not None else None, )