Update notebooks
This commit is contained in:
@@ -85,11 +85,30 @@
|
||||
"\"\"\"Capacitated Vehicle Routing Problem (CVRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a CVRP\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" problem while allowing multiple trips, i.e., vehicles can return to a depot\n",
|
||||
" to reset their load (\"reload\").\n",
|
||||
"\n",
|
||||
" A description of the CVRP problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"\n",
|
||||
" In order to implement multiple trips, new nodes are introduced at the same\n",
|
||||
" locations of the original depots. These additional nodes can be dropped\n",
|
||||
" from the schedule at 0 cost.\n",
|
||||
"\n",
|
||||
" The max_slack parameter associated to the capacity constraints of all nodes\n",
|
||||
" can be set to be the maximum of the vehicles' capacities, rather than 0 like\n",
|
||||
" in a traditional CVRP. Slack is required since before a solution is found,\n",
|
||||
" it is not known how much capacity will be transferred at the new nodes. For\n",
|
||||
" all the other (original) nodes, the slack is then re-set to 0.\n",
|
||||
"\n",
|
||||
" The above two considerations are implemented in `add_capacity_constraints()`.\n",
|
||||
"\n",
|
||||
" Last, it is useful to set a large distance between the initial depot and the\n",
|
||||
" new nodes introduced, to avoid schedules having spurious transits through\n",
|
||||
" those new nodes unless it's necessary to reload. This consideration is taken\n",
|
||||
" into account in `create_distance_evaluator()`.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
@@ -109,9 +128,9 @@
|
||||
" # Locations in block unit\n",
|
||||
" _locations = [\n",
|
||||
" (4, 4), # depot\n",
|
||||
" (4, 4), # unload depot_prime\n",
|
||||
" (4, 4), # unload depot_first\n",
|
||||
" (4, 4), # unload depot_second\n",
|
||||
" (4, 4), # unload depot_fourth\n",
|
||||
" (4, 4), # unload depot_third\n",
|
||||
" (4, 4), # unload depot_fourth\n",
|
||||
" (4, 4), # unload depot_fifth\n",
|
||||
" (2, 0),\n",
|
||||
@@ -139,11 +158,11 @@
|
||||
" data['num_locations'] = len(data['locations'])\n",
|
||||
" data['demands'] = \\\n",
|
||||
" [0, # depot\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity, # unload depot_first\n",
|
||||
" -_capacity, # unload depot_second\n",
|
||||
" -_capacity, # unload depot_third\n",
|
||||
" -_capacity, # unload depot_fourth\n",
|
||||
" -_capacity, # unload depot_fifth\n",
|
||||
" 3, 3, # 1, 2\n",
|
||||
" 3, 4, # 3, 4\n",
|
||||
" 3, 4, # 5, 6\n",
|
||||
@@ -155,11 +174,11 @@
|
||||
" data['time_per_demand_unit'] = 5 # 5 minutes/unit\n",
|
||||
" data['time_windows'] = \\\n",
|
||||
" [(0, 0), # depot\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000), # unload depot_first\n",
|
||||
" (0, 1000), # unload depot_second\n",
|
||||
" (0, 1000), # unload depot_third\n",
|
||||
" (0, 1000), # unload depot_fourth\n",
|
||||
" (0, 1000), # unload depot_fifth\n",
|
||||
" (75, 850), (75, 850), # 1, 2\n",
|
||||
" (60, 700), (45, 550), # 3, 4\n",
|
||||
" (0, 800), (50, 600), # 5, 6\n",
|
||||
@@ -253,14 +272,14 @@
|
||||
" # so we have CumulVar = 10(current load) + -15(unload) + 5(slack) = 0.\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie(capacity)\n",
|
||||
" # Allow to drop reloading nodes with zero cost.\n",
|
||||
" for node_index in [1, 2, 3, 4, 5]:\n",
|
||||
" index = manager.NodeToIndex(node_index)\n",
|
||||
" for node in [1, 2, 3, 4, 5]:\n",
|
||||
" node_index = manager.NodeToIndex(node)\n",
|
||||
" routing.AddDisjunction([node_index], 0)\n",
|
||||
"\n",
|
||||
" # Allow to drop regular node with a cost.\n",
|
||||
" for node_index in range(6, len(data['demands'])):\n",
|
||||
" index = manager.NodeToIndex(node_index)\n",
|
||||
" capacity_dimension.SlackVar(index).SetValue(0)\n",
|
||||
" for node in range(6, len(data['demands'])):\n",
|
||||
" node_index = manager.NodeToIndex(node)\n",
|
||||
" capacity_dimension.SlackVar(node_index).SetValue(0)\n",
|
||||
" routing.AddDisjunction([node_index], 100_000)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
|
||||
@@ -67,10 +67,8 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!/usr/bin/env python\n",
|
||||
"# This Python file uses the following encoding: utf-8\n",
|
||||
"# Copyright 2015 Tin Arm Engineering AB\n",
|
||||
"# Copyright 2018 Google LLC\n",
|
||||
"#!/usr/bin/env python3\n",
|
||||
"# Copyright 2010-2021 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
@@ -82,6 +80,7 @@
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Capacitated Vehicle Routing Problem with Time Windows (CVRPTW).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a CVRPTW\n",
|
||||
@@ -92,23 +91,21 @@
|
||||
" Distances are in meters and time in minutes.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [START import]\n",
|
||||
"import functools\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"# [START data_model]\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem\"\"\"\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" # Locations in block unit\n",
|
||||
" _locations = \\\n",
|
||||
" [(4, 4), # depot\n",
|
||||
" (2, 0), (8, 0), # locations to visit\n",
|
||||
" locations_ = \\\n",
|
||||
" [(4, 4), # depot\n",
|
||||
" (2, 0), (8, 0), # locations to visit\n",
|
||||
" (0, 1), (1, 1),\n",
|
||||
" (5, 2), (7, 2),\n",
|
||||
" (3, 3), (6, 3),\n",
|
||||
@@ -120,28 +117,28 @@
|
||||
" # Manhattan average block: 750ft x 264ft -> 228m x 80m\n",
|
||||
" # here we use: 114m x 80m city block\n",
|
||||
" # src: https://nyti.ms/2GDoRIe \"NY Times: Know Your distance\"\n",
|
||||
" data['locations'] = [(l[0] * 114, l[1] * 80) for l in _locations]\n",
|
||||
" data['num_locations'] = len(data['locations'])\n",
|
||||
" data['locations'] = [(l[0] * 114, l[1] * 80) for l in locations_]\n",
|
||||
" data['numlocations_'] = len(data['locations'])\n",
|
||||
" data['time_windows'] = \\\n",
|
||||
" [(0, 0),\n",
|
||||
" (75, 85), (75, 85), # 1, 2\n",
|
||||
" (60, 70), (45, 55), # 3, 4\n",
|
||||
" (0, 8), (50, 60), # 5, 6\n",
|
||||
" (0, 10), (10, 20), # 7, 8\n",
|
||||
" (0, 10), (75, 85), # 9, 10\n",
|
||||
" (85, 95), (5, 15), # 11, 12\n",
|
||||
" (15, 25), (10, 20), # 13, 14\n",
|
||||
" (45, 55), (30, 40)] # 15, 16\n",
|
||||
" (75, 85), (75, 85), # 1, 2\n",
|
||||
" (60, 70), (45, 55), # 3, 4\n",
|
||||
" (0, 8), (50, 60), # 5, 6\n",
|
||||
" (0, 10), (10, 20), # 7, 8\n",
|
||||
" (0, 10), (75, 85), # 9, 10\n",
|
||||
" (85, 95), (5, 15), # 11, 12\n",
|
||||
" (15, 25), (10, 20), # 13, 14\n",
|
||||
" (45, 55), (30, 40)] # 15, 16\n",
|
||||
" data['demands'] = \\\n",
|
||||
" [0, # depot\n",
|
||||
" 1, 1, # 1, 2\n",
|
||||
" 2, 4, # 3, 4\n",
|
||||
" 2, 4, # 5, 6\n",
|
||||
" 8, 8, # 7, 8\n",
|
||||
" 1, 2, # 9,10\n",
|
||||
" 1, 2, # 11,12\n",
|
||||
" 4, 4, # 13, 14\n",
|
||||
" 8, 8] # 15, 16\n",
|
||||
" [0, # depot\n",
|
||||
" 1, 1, # 1, 2\n",
|
||||
" 2, 4, # 3, 4\n",
|
||||
" 2, 4, # 5, 6\n",
|
||||
" 8, 8, # 7, 8\n",
|
||||
" 1, 2, # 9,10\n",
|
||||
" 1, 2, # 11,12\n",
|
||||
" 4, 4, # 13, 14\n",
|
||||
" 8, 8] # 15, 16\n",
|
||||
" data['time_per_demand_unit'] = 5 # 5 minutes/unit\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['breaks'] = [(2, False), (2, False), (2, False), (2, False)]\n",
|
||||
@@ -149,33 +146,31 @@
|
||||
" data['vehicle_speed'] = 83 # Travel speed: 5km/h converted in m/min\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#######################\n",
|
||||
"# Problem Constraints #\n",
|
||||
"#######################\n",
|
||||
"def manhattan_distance(position_1, position_2):\n",
|
||||
" \"\"\"Computes the Manhattan distance between two points\"\"\"\n",
|
||||
" return (\n",
|
||||
" abs(position_1[0] - position_2[0]) + abs(position_1[1] - position_2[1]))\n",
|
||||
" \"\"\"Computes the Manhattan distance between two points.\"\"\"\n",
|
||||
" return (abs(position_1[0] - position_2[0]) +\n",
|
||||
" abs(position_1[1] - position_2[1]))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" distances_ = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in range(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in range(data['num_locations']):\n",
|
||||
" for from_node in range(data['numlocations_']):\n",
|
||||
" distances_[from_node] = {}\n",
|
||||
" for to_node in range(data['numlocations_']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" distances_[from_node][to_node] = 0\n",
|
||||
" else:\n",
|
||||
" _distances[from_node][to_node] = (manhattan_distance(\n",
|
||||
" distances_[from_node][to_node] = (manhattan_distance(\n",
|
||||
" data['locations'][from_node], data['locations'][to_node]))\n",
|
||||
"\n",
|
||||
" def distance_evaluator(manager, from_node, to_node):\n",
|
||||
" \"\"\"Returns the manhattan distance between the two nodes\"\"\"\n",
|
||||
" return _distances[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" \"\"\"Returns the manhattan distance between the two nodes.\"\"\"\n",
|
||||
" return distances_[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
@@ -183,17 +178,17 @@
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\n",
|
||||
" _demands = data['demands']\n",
|
||||
" demands_ = data['demands']\n",
|
||||
"\n",
|
||||
" def demand_evaluator(manager, node):\n",
|
||||
" \"\"\"Returns the demand of the current node\"\"\"\n",
|
||||
" return _demands[manager.IndexToNode(node)]\n",
|
||||
" \"\"\"Returns the demand of the current node.\"\"\"\n",
|
||||
" return demands_[manager.IndexToNode(node)]\n",
|
||||
"\n",
|
||||
" return demand_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" \"\"\"Adds capacity constraint.\"\"\"\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
@@ -215,45 +210,46 @@
|
||||
" if from_node == to_node:\n",
|
||||
" travel_time = 0\n",
|
||||
" else:\n",
|
||||
" travel_time = manhattan_distance(data['locations'][from_node], data[\n",
|
||||
" 'locations'][to_node]) / data['vehicle_speed']\n",
|
||||
" travel_time = manhattan_distance(\n",
|
||||
" data['locations'][from_node],\n",
|
||||
" data['locations'][to_node]) / data['vehicle_speed']\n",
|
||||
" return travel_time\n",
|
||||
"\n",
|
||||
" _total_time = {}\n",
|
||||
" total_time_ = {}\n",
|
||||
" # precompute total time to have time callback in O(1)\n",
|
||||
" for from_node in range(data['num_locations']):\n",
|
||||
" _total_time[from_node] = {}\n",
|
||||
" for to_node in range(data['num_locations']):\n",
|
||||
" for from_node in range(data['numlocations_']):\n",
|
||||
" total_time_[from_node] = {}\n",
|
||||
" for to_node in range(data['numlocations_']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _total_time[from_node][to_node] = 0\n",
|
||||
" total_time_[from_node][to_node] = 0\n",
|
||||
" else:\n",
|
||||
" _total_time[from_node][to_node] = int(\n",
|
||||
" service_time(data, from_node) + travel_time(\n",
|
||||
" data, from_node, to_node))\n",
|
||||
" total_time_[from_node][to_node] = int(\n",
|
||||
" service_time(data, from_node) +\n",
|
||||
" travel_time(data, from_node, to_node))\n",
|
||||
"\n",
|
||||
" def time_evaluator(manager, from_node, to_node):\n",
|
||||
" \"\"\"Returns the total time between the two nodes\"\"\"\n",
|
||||
" return _total_time[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" \"\"\"Returns the total time between the two nodes.\"\"\"\n",
|
||||
" return total_time_[manager.IndexToNode(from_node)][manager.IndexToNode(\n",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return time_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_time_window_constraints(routing, manager, data, time_evaluator_index):\n",
|
||||
" \"\"\"Add Global Span constraint\"\"\"\n",
|
||||
" \"\"\"Add Global Span constraint.\"\"\"\n",
|
||||
" time = 'Time'\n",
|
||||
" horizon = 120\n",
|
||||
" routing.AddDimension(\n",
|
||||
" time_evaluator_index,\n",
|
||||
" horizon, # allow waiting time\n",
|
||||
" horizon, # maximum time per vehicle\n",
|
||||
" False, # don't force start cumul to zero since we are giving TW to start nodes\n",
|
||||
" False, # don't force start cumul to zero\n",
|
||||
" time)\n",
|
||||
" time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
" # Add time window constraints for each location except depot\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for location_idx, time_window in enumerate(data['time_windows']):\n",
|
||||
" if location_idx == 0:\n",
|
||||
" if location_idx == data['depot']:\n",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n",
|
||||
@@ -265,15 +261,15 @@
|
||||
" time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],\n",
|
||||
" data['time_windows'][0][1])\n",
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Warning: Slack var is not defined for vehicle's end node\n",
|
||||
" #routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id)))\n",
|
||||
" # The time window at the end node was impliclty set in the time dimension\n",
|
||||
" # definition to be [0, horizon].\n",
|
||||
" # Warning: Slack var is not defined for vehicle end nodes and should not\n",
|
||||
" # be added to the assignment.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
"\n",
|
||||
" print('Breaks:')\n",
|
||||
@@ -281,10 +277,9 @@
|
||||
" for i in range(intervals.Size()):\n",
|
||||
" brk = intervals.Element(i)\n",
|
||||
" if brk.PerformedValue() == 1:\n",
|
||||
" print('{}: Start({}) Duration({})'.format(\n",
|
||||
" brk.Var().Name(),\n",
|
||||
" brk.StartValue(),\n",
|
||||
" brk.DurationValue()))\n",
|
||||
" print('{}: Start({}) Duration({})'.format(brk.Var().Name(),\n",
|
||||
" brk.StartValue(),\n",
|
||||
" brk.DurationValue()))\n",
|
||||
" else:\n",
|
||||
" print('{}: Unperformed'.format(brk.Var().Name()))\n",
|
||||
"\n",
|
||||
@@ -302,10 +297,8 @@
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" slack_var = time_dimension.SlackVar(index)\n",
|
||||
" plan_output += ' {0} Load({1}) Time({2},{3}) Slack({4},{5}) ->'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var),\n",
|
||||
" assignment.Max(time_var),\n",
|
||||
" manager.IndexToNode(index), assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var), assignment.Max(time_var),\n",
|
||||
" assignment.Min(slack_var), assignment.Max(slack_var))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
@@ -313,10 +306,8 @@
|
||||
" vehicle_id)\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" slack_var = time_dimension.SlackVar(index)\n",
|
||||
" plan_output += ' {0} Load({1}) Time({2},{3})\\n'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" manager.IndexToNode(index), assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var), assignment.Max(time_var))\n",
|
||||
" plan_output += 'Distance of the route: {0}m\\n'.format(distance)\n",
|
||||
" plan_output += 'Load of the route: {}\\n'.format(\n",
|
||||
@@ -330,17 +321,17 @@
|
||||
" print('Total Distance of all routes: {0}m'.format(total_distance))\n",
|
||||
" print('Total Load of all routes: {}'.format(total_load))\n",
|
||||
" print('Total Time of all routes: {0}min'.format(total_time))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"\"\"\"Entry point of the program.\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"# [START data]\n",
|
||||
"data = create_data_model()\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['numlocations_'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
@@ -348,47 +339,57 @@
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_distance_evaluator(data), manager))\n",
|
||||
" functools.partial(create_distance_evaluator(data), manager))\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add Capacity constraint\n",
|
||||
"demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" partial(create_demand_evaluator(data), manager))\n",
|
||||
" functools.partial(create_demand_evaluator(data), manager))\n",
|
||||
"add_capacity_constraints(routing, data, demand_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add Time Window constraint\n",
|
||||
"time_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_time_evaluator(data), manager))\n",
|
||||
" functools.partial(create_time_evaluator(data), manager))\n",
|
||||
"add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add breaks\n",
|
||||
"time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
"time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
"node_visit_transit = {}\n",
|
||||
"for n in range(routing.Size()):\n",
|
||||
" if n >= data['num_locations']:\n",
|
||||
" node_visit_transit[n] = 0\n",
|
||||
" else:\n",
|
||||
" node_visit_transit[n] = int(\n",
|
||||
" data['demands'][n] * data['time_per_demand_unit'])\n",
|
||||
"for index in range(routing.Size()):\n",
|
||||
" node = manager.IndexToNode(index)\n",
|
||||
" node_visit_transit[index] = int(data['demands'][node] *\n",
|
||||
" data['time_per_demand_unit'])\n",
|
||||
"\n",
|
||||
"break_intervals = {}\n",
|
||||
"#for v in range(data['num_vehicles']):\n",
|
||||
"for v in [0]:\n",
|
||||
"for v in range(data['num_vehicles']):\n",
|
||||
" vehicle_break = data['breaks'][v]\n",
|
||||
" break_intervals[v] = [\n",
|
||||
" routing.solver().FixedDurationIntervalVar(\n",
|
||||
" 15, 100, vehicle_break[0], vehicle_break[1], 'Break for vehicle {}'.format(v))\n",
|
||||
" ]\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(\n",
|
||||
" break_intervals[v], v, node_visit_transit)\n",
|
||||
" routing.solver().FixedDurationIntervalVar(15, 100, vehicle_break[0],\n",
|
||||
" vehicle_break[1],\n",
|
||||
" f'Break for vehicle {v}')\n",
|
||||
" ]\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(break_intervals[v], v,\n",
|
||||
" node_visit_transit.values())\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"# [START parameters]\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"else:\n",
|
||||
" print('No solution found!')\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
|
||||
263
examples/notebook/constraint_solver/vrp_breaks.ipynb
Normal file
263
examples/notebook/constraint_solver/vrp_breaks.ipynb
Normal file
@@ -0,0 +1,263 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2020 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"you may not use this file except in compliance with the License.\n",
|
||||
"You may obtain a copy of the License at\n",
|
||||
"\n",
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"\n",
|
||||
"Unless required by applicable law or agreed to in writing, software\n",
|
||||
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"See the License for the specific language governing permissions and\n",
|
||||
"limitations under the License.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# vrp_breaks"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/master/examples/notebook/constraint_solver/vrp_breaks.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
|
||||
"</td>\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://github.com/google/or-tools/blob/master/ortools/constraint_solver/samples/vrp_breaks.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/github_32px.png\"/>View source on GitHub</a>\n",
|
||||
"</td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install ortools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!/usr/bin/env python3\n",
|
||||
"# Copyright 2010-2021 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicle Routing Problem with Time Windows (CVRPTW).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a CVRPTW\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Durations are in minutes.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START data_model]\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" data['time_matrix'] = [\n",
|
||||
" [0, 27, 38, 34, 29, 13, 25, 9, 15, 9, 26, 25, 19, 17, 23, 38, 33],\n",
|
||||
" [27, 0, 34, 15, 9, 25, 36, 17, 34, 37, 54, 29, 24, 33, 50, 43, 60],\n",
|
||||
" [38, 34, 0, 49, 43, 25, 13, 40, 23, 37, 20, 63, 58, 56, 39, 77, 37],\n",
|
||||
" [34, 15, 49, 0, 5, 32, 43, 25, 42, 44, 61, 25, 31, 41, 58, 28, 67],\n",
|
||||
" [29, 9, 43, 5, 0, 26, 38, 19, 36, 38, 55, 20, 25, 35, 52, 33, 62],\n",
|
||||
" [13, 25, 25, 32, 26, 0, 11, 15, 9, 12, 29, 38, 33, 31, 25, 52, 35],\n",
|
||||
" [25, 36, 13, 43, 38, 11, 0, 26, 9, 23, 17, 50, 44, 42, 25, 63, 24],\n",
|
||||
" [9, 17, 40, 25, 19, 15, 26, 0, 17, 19, 36, 23, 17, 16, 33, 37, 42],\n",
|
||||
" [15, 34, 23, 42, 36, 9, 9, 17, 0, 13, 19, 40, 34, 33, 16, 54, 25],\n",
|
||||
" [9, 37, 37, 44, 38, 12, 23, 19, 13, 0, 17, 26, 21, 19, 13, 40, 23],\n",
|
||||
" [26, 54, 20, 61, 55, 29, 17, 36, 19, 17, 0, 43, 38, 36, 19, 57, 17],\n",
|
||||
" [25, 29, 63, 25, 20, 38, 50, 23, 40, 26, 43, 0, 5, 15, 32, 13, 42],\n",
|
||||
" [19, 24, 58, 31, 25, 33, 44, 17, 34, 21, 38, 5, 0, 9, 26, 19, 36],\n",
|
||||
" [17, 33, 56, 41, 35, 31, 42, 16, 33, 19, 36, 15, 9, 0, 17, 21, 26],\n",
|
||||
" [23, 50, 39, 58, 52, 25, 25, 33, 16, 13, 19, 32, 26, 17, 0, 38, 9],\n",
|
||||
" [38, 43, 77, 28, 33, 52, 63, 37, 54, 40, 57, 13, 19, 21, 38, 0, 39],\n",
|
||||
" [33, 60, 37, 67, 62, 35, 24, 42, 25, 23, 17, 42, 36, 26, 9, 39, 0],\n",
|
||||
" ]\n",
|
||||
" data['service_time'] = [15] * len(data['time_matrix']) # 15 min of service time\n",
|
||||
" data['service_time'][data['depot']] = 0\n",
|
||||
" assert(len(data['time_matrix']) == len(data['service_time']))\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(solution.ObjectiveValue()))\n",
|
||||
"\n",
|
||||
" print('Breaks:')\n",
|
||||
" intervals = solution.IntervalVarContainer()\n",
|
||||
" for i in range(intervals.Size()):\n",
|
||||
" brk = intervals.Element(i)\n",
|
||||
" if brk.PerformedValue() == True:\n",
|
||||
" print(f'{brk.Var().Name()}: Start({brk.StartValue()}) Duration({brk.DurationValue()})')\n",
|
||||
" else:\n",
|
||||
" print(f'{brk.Var().Name()}: Unperformed')\n",
|
||||
"\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += f'{manager.IndexToNode(index)} Time({solution.Value(time_var)}) -> '\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += f'{manager.IndexToNode(index)} Time({solution.Value(time_var)})\\n'\n",
|
||||
" plan_output += f'Time of the route: {solution.Value(time_var)}min\\n'\n",
|
||||
" print(plan_output)\n",
|
||||
" total_time += solution.Value(time_var)\n",
|
||||
" print(f'Total time of all routes: {total_time}min')\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the VRP with time windows.\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"# [START data]\n",
|
||||
"data = create_data_model()\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# Create the routing index manager.\n",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']), data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START transit_callback]\n",
|
||||
"def time_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the travel time + service time between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to time matrix NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" to_node = manager.IndexToNode(to_index)\n",
|
||||
" return data['time_matrix'][from_node][to_node] + data['service_time'][from_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(time_callback)\n",
|
||||
"# [END transit_callback]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Time Windows constraint.\n",
|
||||
"time = 'Time'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 10, # needed optional waiting time to place break\n",
|
||||
" 180, # maximum time per vehicle\n",
|
||||
" True, # Force start cumul to zero.\n",
|
||||
" time)\n",
|
||||
"time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
"time_dimension.SetGlobalSpanCostCoefficient(10)\n",
|
||||
"\n",
|
||||
"# Breaks\n",
|
||||
"# [START break_constraint]\n",
|
||||
"# warning: Need a pre-travel array using the solver's index order.\n",
|
||||
"node_visit_transit = [0] * routing.Size()\n",
|
||||
"for index in range(routing.Size()):\n",
|
||||
" node = manager.IndexToNode(index)\n",
|
||||
" node_visit_transit[index] = data['service_time'][node]\n",
|
||||
"\n",
|
||||
"break_intervals = {}\n",
|
||||
"for v in range(data['num_vehicles']):\n",
|
||||
" break_intervals[v] = [\n",
|
||||
" routing.solver().FixedDurationIntervalVar(\n",
|
||||
" 50, # start min\n",
|
||||
" 60, # start max\n",
|
||||
" 10, # duration: 10 min\n",
|
||||
" False, # optional: no\n",
|
||||
" f'Break for vehicle {v}')\n",
|
||||
" ]\n",
|
||||
" time_dimension.SetBreakIntervalsOfVehicle(\n",
|
||||
" break_intervals[v], # breaks\n",
|
||||
" v, # vehicle index\n",
|
||||
" node_visit_transit)\n",
|
||||
"# [END break_constraint]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic.\n",
|
||||
"# [START parameters]\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n",
|
||||
"search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
"#search_parameters.log_search = True\n",
|
||||
"search_parameters.time_limit.FromSeconds(2)\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"solution = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if solution:\n",
|
||||
" print_solution(manager, routing, solution)\n",
|
||||
"else:\n",
|
||||
" print('No solution found !')\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -67,6 +67,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!/usr/bin/env python3\n",
|
||||
"# Copyright 2010-2018 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!/usr/bin/env python3\n",
|
||||
"# Copyright 2010-2018 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
@@ -209,15 +210,17 @@
|
||||
"time_dimension = routing.GetDimensionOrDie(time)\n",
|
||||
"# Add time window constraints for each location except depot.\n",
|
||||
"for location_idx, time_window in enumerate(data['time_windows']):\n",
|
||||
" if location_idx == 0:\n",
|
||||
" if location_idx == data['depot']:\n",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n",
|
||||
"# Add time window constraints for each vehicle start node.\n",
|
||||
"depot_idx = data['depot']\n",
|
||||
"for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(data['time_windows'][0][0],\n",
|
||||
" data['time_windows'][0][1])\n",
|
||||
" time_dimension.CumulVar(index).SetRange(\n",
|
||||
" data['time_windows'][depot_idx][0],\n",
|
||||
" data['time_windows'][depot_idx][1])\n",
|
||||
"# [END time_windows_constraint]\n",
|
||||
"\n",
|
||||
"# Instantiate route start and end times to produce feasible times.\n",
|
||||
|
||||
232
examples/notebook/constraint_solver/vrp_tokens.ipynb
Normal file
232
examples/notebook/constraint_solver/vrp_tokens.ipynb
Normal file
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2020 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"you may not use this file except in compliance with the License.\n",
|
||||
"You may obtain a copy of the License at\n",
|
||||
"\n",
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"\n",
|
||||
"Unless required by applicable law or agreed to in writing, software\n",
|
||||
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"See the License for the specific language governing permissions and\n",
|
||||
"limitations under the License.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# vrp_tokens"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/master/examples/notebook/constraint_solver/vrp_tokens.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
|
||||
"</td>\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://github.com/google/or-tools/blob/master/ortools/constraint_solver/samples/vrp_tokens.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/github_32px.png\"/>View source on GitHub</a>\n",
|
||||
"</td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install ortools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"#!/usr/bin/env python3\n",
|
||||
"# Copyright 2020 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"\"\"\"\n",
|
||||
"Simple VRP with special locations which need to be visited at end of the route.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem.\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" # Special location don't consume token, while regular one consume one\n",
|
||||
" data['tokens'] = [\n",
|
||||
" 0, # 0 depot\n",
|
||||
" 0, # 1 special node\n",
|
||||
" 0, # 2 special node\n",
|
||||
" 0, # 3 special node\n",
|
||||
" 0, # 4 special node\n",
|
||||
" 0, # 5 special node\n",
|
||||
" -1, # 6\n",
|
||||
" -1, # 7\n",
|
||||
" -1, # 8\n",
|
||||
" -1, # 9\n",
|
||||
" -1, # 10\n",
|
||||
" -1, # 11\n",
|
||||
" -1, # 12\n",
|
||||
" -1, # 13\n",
|
||||
" -1, # 14\n",
|
||||
" -1, # 15\n",
|
||||
" -1, # 16\n",
|
||||
" -1, # 17\n",
|
||||
" -1, # 18\n",
|
||||
" ]\n",
|
||||
" # just need to be big enough, not a limiting factor\n",
|
||||
" data['vehicle_tokens'] = [20, 20, 20, 20]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" token_dimension = routing.GetDimensionOrDie('Token')\n",
|
||||
" total_distance = 0\n",
|
||||
" total_token = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" plan_output = f'Route for vehicle {vehicle_id}:\\n'\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" total_token += solution.Value(token_dimension.CumulVar(index))\n",
|
||||
" route_distance = 0\n",
|
||||
" route_token = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" token_var = token_dimension.CumulVar(index)\n",
|
||||
" route_token = solution.Value(token_var)\n",
|
||||
" plan_output += f' {node_index} Token({route_token}) -> '\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" token_var = token_dimension.CumulVar(index)\n",
|
||||
" route_token = solution.Value(token_var)\n",
|
||||
" plan_output += f' {node_index} Token({route_token})\\n'\n",
|
||||
" plan_output += f'Distance of the route: {route_distance}m\\n'\n",
|
||||
" total_distance += route_distance\n",
|
||||
" print(plan_output)\n",
|
||||
" print('Total distance of all routes: {}m'.format(total_distance))\n",
|
||||
" print('Total token of all routes: {}'.format(total_token))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager.\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" len(data['tokens']),\n",
|
||||
" data['num_vehicles'],\n",
|
||||
" data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the distance between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to distance matrix NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" to_node = manager.IndexToNode(to_index)\n",
|
||||
" return 10\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # null slack\n",
|
||||
" 3000, # maximum distance per vehicle\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" \"distance\")\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(\"distance\")\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
"# Add Token constraint.\n",
|
||||
"def token_callback(from_index):\n",
|
||||
" \"\"\"Returns the number of token consumed by the node.\"\"\"\n",
|
||||
" # Convert from routing variable Index to tokens NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" return data['tokens'][from_node]\n",
|
||||
"\n",
|
||||
"token_callback_index = routing.RegisterUnaryTransitCallback(token_callback)\n",
|
||||
"routing.AddDimensionWithVehicleCapacity(\n",
|
||||
" token_callback_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_tokens'], # vehicle maximum tokens\n",
|
||||
" False, # start cumul to zero\n",
|
||||
" 'Token')\n",
|
||||
"# Add constraint: special node can only be visited if token remaining is zero\n",
|
||||
"token_dimension = routing.GetDimensionOrDie('Token')\n",
|
||||
"for node in range(1, 6):\n",
|
||||
" index = manager.NodeToIndex(node)\n",
|
||||
" routing.solver().Add(token_dimension.CumulVar(index) == 0)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic.\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n",
|
||||
"search_parameters.local_search_metaheuristic = (\n",
|
||||
" routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n",
|
||||
"search_parameters.time_limit.FromSeconds(1)\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"solution = routing.SolveWithParameters(search_parameters)\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"if solution:\n",
|
||||
" print_solution(manager, routing, solution)\n",
|
||||
"else:\n",
|
||||
" print(\"No solution found !\")\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -87,6 +87,7 @@
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
@@ -106,21 +107,20 @@
|
||||
" print(plan_output)\n",
|
||||
" max_route_distance = max(route_distance, max_route_distance)\n",
|
||||
" print('Maximum of the route distances: {}m'.format(max_route_distance))\n",
|
||||
"# [END solution_printer]\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"# [START data]\n",
|
||||
"num_locations = 20;\n",
|
||||
"num_vehicles = 5;\n",
|
||||
"depot = 0;\n",
|
||||
"num_locations = 20\n",
|
||||
"num_vehicles = 5\n",
|
||||
"depot = 0\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# Create the routing index manager.\n",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" num_locations, num_vehicles, depot)\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot)\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
@@ -132,10 +132,8 @@
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START transit_callback]\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" # pylint: disable=unused-argument\n",
|
||||
" \"\"\"Returns the distance between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to distance matrix NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" to_node = manager.IndexToNode(to_index)\n",
|
||||
" return 1\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
"\"\"\"Integer programming examples that show how to use the APIs.\"\"\"\n",
|
||||
"\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"from ortools.init import pywrapinit\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def Announce(solver, api_type):\n",
|
||||
@@ -167,6 +168,7 @@
|
||||
" RunIntegerExampleNaturalLanguageAPI('CBC')\n",
|
||||
" RunIntegerExampleNaturalLanguageAPI('SCIP')\n",
|
||||
" RunIntegerExampleNaturalLanguageAPI('SAT')\n",
|
||||
" RunIntegerExampleNaturalLanguageAPI('Gurobi')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def RunAllIntegerExampleCppStyleAPI():\n",
|
||||
@@ -174,6 +176,7 @@
|
||||
" RunIntegerExampleCppStyleAPI('CBC')\n",
|
||||
" RunIntegerExampleCppStyleAPI('SCIP')\n",
|
||||
" RunIntegerExampleCppStyleAPI('SAT')\n",
|
||||
" RunIntegerExampleCppStyleAPI('Gurobi')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"RunAllIntegerExampleNaturalLanguageAPI()\n",
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
" cost_coefficients.append(max_cost * (length - soft_max))\n",
|
||||
"\n",
|
||||
" # Just forbid any sequence of true variables with length hard_max + 1\n",
|
||||
" for start in range(len(works) - hard_max - 1):\n",
|
||||
" for start in range(len(works) - hard_max):\n",
|
||||
" model.AddBoolOr(\n",
|
||||
" [works[i].Not() for i in range(start, start + hard_max + 1)])\n",
|
||||
" return cost_literals, cost_coefficients\n",
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
"for i in range(num_workers):\n",
|
||||
" t = []\n",
|
||||
" for j in range(num_tasks):\n",
|
||||
" t.append(model.NewBoolVar('x[%i,%i]' % (i, j)))\n",
|
||||
" t.append(model.NewBoolVar(f'x[{i},{j}]'))\n",
|
||||
" x.append(t)\n",
|
||||
"# [END variables]\n",
|
||||
"\n",
|
||||
@@ -143,13 +143,13 @@
|
||||
"# Print solution.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:\n",
|
||||
" print('Total cost = %i' % solver.ObjectiveValue())\n",
|
||||
" print(f'Total cost = {solver.ObjectiveValue()}')\n",
|
||||
" print()\n",
|
||||
" for i in range(num_workers):\n",
|
||||
" for j in range(num_tasks):\n",
|
||||
" if solver.BooleanValue(x[i][j]):\n",
|
||||
" print('Worker ', i, ' assigned to task ', j, ' Cost = ',\n",
|
||||
" costs[i][j])\n",
|
||||
" print(\n",
|
||||
" f'Worker {i} assigned to task {j} Cost = {costs[i][j]}')\n",
|
||||
"else:\n",
|
||||
" print('No solution found.')\n",
|
||||
"# [END print_solution]\n",
|
||||
|
||||
135
examples/notebook/sat/assumptions_sample_sat.ipynb
Normal file
135
examples/notebook/sat/assumptions_sample_sat.ipynb
Normal file
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2020 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"you may not use this file except in compliance with the License.\n",
|
||||
"You may obtain a copy of the License at\n",
|
||||
"\n",
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"\n",
|
||||
"Unless required by applicable law or agreed to in writing, software\n",
|
||||
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"See the License for the specific language governing permissions and\n",
|
||||
"limitations under the License.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# assumptions_sample_sat"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/master/examples/notebook/sat/assumptions_sample_sat.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
|
||||
"</td>\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://github.com/google/or-tools/blob/master/ortools/sat/samples/assumptions_sample_sat.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/github_32px.png\"/>View source on GitHub</a>\n",
|
||||
"</td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install ortools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2021 Xiang Chen\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"\"\"\"Code sample that solves a model and gets the infeasibility assumptions.\"\"\"\n",
|
||||
"# [START program]\n",
|
||||
"# [START import]\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Showcases assumptions.\"\"\"\n",
|
||||
"# Creates the model.\n",
|
||||
"# [START model]\n",
|
||||
"model = cp_model.CpModel()\n",
|
||||
"# [END model]\n",
|
||||
"\n",
|
||||
"# Creates the variables.\n",
|
||||
"# [START variables]\n",
|
||||
"x = model.NewIntVar(0, 10, 'x')\n",
|
||||
"y = model.NewIntVar(0, 10, 'y')\n",
|
||||
"z = model.NewIntVar(0, 10, 'z')\n",
|
||||
"a = model.NewBoolVar('a')\n",
|
||||
"b = model.NewBoolVar('b')\n",
|
||||
"c = model.NewBoolVar('c')\n",
|
||||
"# [END variables]\n",
|
||||
"\n",
|
||||
"# Creates the constraints.\n",
|
||||
"# [START constraints]\n",
|
||||
"model.Add(x > y).OnlyEnforceIf(a)\n",
|
||||
"model.Add(y > z).OnlyEnforceIf(b)\n",
|
||||
"model.Add(z > x).OnlyEnforceIf(c)\n",
|
||||
"# [END constraints]\n",
|
||||
"\n",
|
||||
"# Add assumptions\n",
|
||||
"model.AddAssumptions([a, b, c])\n",
|
||||
"\n",
|
||||
"# Creates a solver and solves.\n",
|
||||
"# [START solve]\n",
|
||||
"solver = cp_model.CpSolver()\n",
|
||||
"status = solver.Solve(model)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution.\n",
|
||||
"# [START print_solution]\n",
|
||||
"print(f'Status = {solver.StatusName(status)}')\n",
|
||||
"if status == cp_model.INFEASIBLE:\n",
|
||||
" print('SufficientAssumptionsForInfeasibility = '\n",
|
||||
" f'{solver.SufficientAssumptionsForInfeasibility()}')\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
146
examples/notebook/sat/copy_model_sample_sat.ipynb
Normal file
146
examples/notebook/sat/copy_model_sample_sat.ipynb
Normal file
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"##### Copyright 2020 Google LLC."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"you may not use this file except in compliance with the License.\n",
|
||||
"You may obtain a copy of the License at\n",
|
||||
"\n",
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"\n",
|
||||
"Unless required by applicable law or agreed to in writing, software\n",
|
||||
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"See the License for the specific language governing permissions and\n",
|
||||
"limitations under the License.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# copy_model_sample_sat"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<table align=\"left\">\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/master/examples/notebook/sat/copy_model_sample_sat.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
|
||||
"</td>\n",
|
||||
"<td>\n",
|
||||
"<a href=\"https://github.com/google/or-tools/blob/master/ortools/sat/samples/copy_model_sample_sat.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/master/tools/github_32px.png\"/>View source on GitHub</a>\n",
|
||||
"</td>\n",
|
||||
"</table>"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"!pip install ortools"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2018 Google LLC\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"\"\"\"Showcases deep copying of a model.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START program]\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def CopyModelSat():\n",
|
||||
" \"\"\"Showcases printing intermediate solutions found during search.\"\"\"\n",
|
||||
" # Creates the model.\n",
|
||||
" # [START model]\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" # [END model]\n",
|
||||
"\n",
|
||||
" # Creates the variables.\n",
|
||||
" # [START variables]\n",
|
||||
" num_vals = 3\n",
|
||||
" x = model.NewIntVar(0, num_vals - 1, 'x')\n",
|
||||
" y = model.NewIntVar(0, num_vals - 1, 'y')\n",
|
||||
" z = model.NewIntVar(0, num_vals - 1, 'z')\n",
|
||||
" # [END variables]\n",
|
||||
"\n",
|
||||
" # Creates the constraints.\n",
|
||||
" # [START constraints]\n",
|
||||
" model.Add(x != y)\n",
|
||||
" # [END constraints]\n",
|
||||
"\n",
|
||||
" # [START objective]\n",
|
||||
" model.Maximize(x + 2 * y + 3 * z)\n",
|
||||
" # [END objective]\n",
|
||||
"\n",
|
||||
" # Creates a solver and solves.\n",
|
||||
" # [START solve]\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
" # [END solve]\n",
|
||||
"\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" print('Optimal value of the original model: {}'.format(\n",
|
||||
" solver.ObjectiveValue()))\n",
|
||||
"\n",
|
||||
" # Copy the model.\n",
|
||||
" copy = cp_model.CpModel()\n",
|
||||
" copy.CopyFrom(model)\n",
|
||||
"\n",
|
||||
" copy_x = copy.GetIntVarFromProtoIndex(x.Index())\n",
|
||||
" copy_y = copy.GetIntVarFromProtoIndex(y.Index())\n",
|
||||
"\n",
|
||||
" copy.Add(copy_x + copy_y <= 1)\n",
|
||||
" status = solver.Solve(copy)\n",
|
||||
"\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" print('Optimal value of the modified model: {}'.format(\n",
|
||||
" solver.ObjectiveValue()))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"CopyModelSat()\n",
|
||||
"# [END program]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
Reference in New Issue
Block a user