Skip to content

Commit 06aea80

Browse files
committed
routing: regen notebooks
1 parent 5dd16d2 commit 06aea80

31 files changed

+611
-180
lines changed
Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "google",
6+
"metadata": {},
7+
"source": [
8+
"##### Copyright 2023 Google LLC."
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"id": "apache",
14+
"metadata": {},
15+
"source": [
16+
"Licensed under the Apache License, Version 2.0 (the \"License\");\n",
17+
"you may not use this file except in compliance with the License.\n",
18+
"You may obtain a copy of the License at\n",
19+
"\n",
20+
" http://www.apache.org/licenses/LICENSE-2.0\n",
21+
"\n",
22+
"Unless required by applicable law or agreed to in writing, software\n",
23+
"distributed under the License is distributed on an \"AS IS\" BASIS,\n",
24+
"WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
25+
"See the License for the specific language governing permissions and\n",
26+
"limitations under the License.\n"
27+
]
28+
},
29+
{
30+
"cell_type": "markdown",
31+
"id": "basename",
32+
"metadata": {},
33+
"source": [
34+
"# permutation_flow_shop"
35+
]
36+
},
37+
{
38+
"cell_type": "markdown",
39+
"id": "link",
40+
"metadata": {},
41+
"source": [
42+
"<table align=\"left\">\n",
43+
"<td>\n",
44+
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/contrib/permutation_flow_shop.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
45+
"</td>\n",
46+
"<td>\n",
47+
"<a href=\"https://github.com/google/or-tools/blob/main/examples/contrib/permutation_flow_shop.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
48+
"</td>\n",
49+
"</table>"
50+
]
51+
},
52+
{
53+
"cell_type": "markdown",
54+
"id": "doc",
55+
"metadata": {},
56+
"source": [
57+
"First, you must install [ortools](https://pypi.org/project/ortools/) package in this colab."
58+
]
59+
},
60+
{
61+
"cell_type": "code",
62+
"execution_count": null,
63+
"id": "install",
64+
"metadata": {},
65+
"outputs": [],
66+
"source": [
67+
"%pip install ortools"
68+
]
69+
},
70+
{
71+
"cell_type": "markdown",
72+
"id": "description",
73+
"metadata": {},
74+
"source": [
75+
"\n",
76+
"This model implements the permutation flow shop problem (PFSP).\n",
77+
"\n",
78+
"In the PFSP, a set of jobs has to be processed on a set of machines. Each job\n",
79+
"must be processed on each machine in sequence and all jobs have to be processed\n",
80+
"in the same order on every machine. The objective is to minimize the makespan.\n",
81+
"\n"
82+
]
83+
},
84+
{
85+
"cell_type": "code",
86+
"execution_count": null,
87+
"id": "code",
88+
"metadata": {},
89+
"outputs": [],
90+
"source": [
91+
"from typing import Sequence\n",
92+
"from dataclasses import dataclass\n",
93+
"from itertools import product\n",
94+
"\n",
95+
"import numpy as np\n",
96+
"\n",
97+
"from ortools.sat.colab import flags\n",
98+
"from google.protobuf import text_format\n",
99+
"from ortools.sat.python import cp_model\n",
100+
"\n",
101+
"_PARAMS = flags.define_string(\n",
102+
" \"params\",\n",
103+
" \"num_search_workers:16\",\n",
104+
" \"Sat solver parameters.\",\n",
105+
")\n",
106+
"\n",
107+
"_TIME_LIMIT = flags.define_float(\n",
108+
" \"time_limit\",\n",
109+
" 60.0,\n",
110+
" \"Time limit in seconds. Default is 60s.\",\n",
111+
")\n",
112+
"\n",
113+
"_LOG = flags.define_boolean(\n",
114+
" \"log\",\n",
115+
" False,\n",
116+
" \"Whether to log the solver output.\",\n",
117+
")\n",
118+
"\n",
119+
"\n",
120+
"@dataclass\n",
121+
"class TaskType:\n",
122+
" \"\"\"\n",
123+
" Small wrapper to hold the start, end, and interval variables of a task.\n",
124+
" \"\"\"\n",
125+
"\n",
126+
" start: cp_model.IntVar\n",
127+
" end: cp_model.IntVar\n",
128+
" interval: cp_model.IntervalVar\n",
129+
"\n",
130+
"\n",
131+
"def permutation_flow_shop(\n",
132+
" processing_times: np.ndarray,\n",
133+
" time_limit: float,\n",
134+
" log: bool,\n",
135+
" params: str\n",
136+
"):\n",
137+
" \"\"\"\n",
138+
" Solves the given permutation flow shop problem instance with OR-Tools.\n",
139+
"\n",
140+
" Parameters\n",
141+
" ----------\n",
142+
" processing_times\n",
143+
" An n-by-m matrix of processing times of the jobs on the machines.\n",
144+
" time_limit\n",
145+
" The time limit in seconds. If not set, the solver runs until an\n",
146+
" optimal solution is found.\n",
147+
" log\n",
148+
" Whether to log the solver output. Default is False.\n",
149+
"\n",
150+
" Raises\n",
151+
" ------\n",
152+
" ValueError\n",
153+
" If the number of lines is greater than 1, i.e., the instance is a\n",
154+
" distributed permutation flow shop problem.\n",
155+
" \"\"\"\n",
156+
" m = cp_model.CpModel()\n",
157+
" num_jobs, num_machines = processing_times.shape\n",
158+
" horizon = processing_times.sum()\n",
159+
"\n",
160+
" # Create interval variables for all tasks (each job/machine pair).\n",
161+
" tasks = {}\n",
162+
" for job, machine in product(range(num_jobs), range(num_machines)):\n",
163+
" start = m.new_int_var(0, horizon, \"\")\n",
164+
" end = m.new_int_var(0, horizon, \"\")\n",
165+
" duration = processing_times[job][machine]\n",
166+
" interval = m.new_interval_var(start, duration, end, \"\")\n",
167+
" tasks[job, machine] = TaskType(start, end, interval)\n",
168+
"\n",
169+
" # No overlap for all job intervals on this machine.\n",
170+
" for machine in range(num_machines):\n",
171+
" intervals = [tasks[job, machine].interval for job in range(num_jobs)]\n",
172+
" m.add_no_overlap(intervals)\n",
173+
"\n",
174+
" # Add precedence constraints between tasks of the same job.\n",
175+
" for job, machine in product(range(num_jobs), range(num_machines - 1)):\n",
176+
" pred = tasks[job, machine]\n",
177+
" succ = tasks[job, machine + 1]\n",
178+
" m.add(pred.end <= succ.start)\n",
179+
"\n",
180+
" # Create arcs for circuit constraints.\n",
181+
" arcs = []\n",
182+
" for idx1 in range(num_jobs):\n",
183+
" arcs.append((0, idx1 + 1, m.new_bool_var(\"start\")))\n",
184+
" arcs.append((idx1 + 1, 0, m.new_bool_var(\"end\")))\n",
185+
"\n",
186+
" lits = {}\n",
187+
" for idx1, idx2 in product(range(num_jobs), repeat=2):\n",
188+
" if idx1 != idx2:\n",
189+
" lit = m.new_bool_var(f\"{idx1} -> {idx2}\")\n",
190+
" lits[idx1, idx2] = lit\n",
191+
" arcs.append((idx1 + 1, idx2 + 1, lit))\n",
192+
"\n",
193+
" m.add_circuit(arcs)\n",
194+
"\n",
195+
" # Enforce that the permutation of jobs is the same on all machines.\n",
196+
" for machine in range(num_machines):\n",
197+
" starts = [tasks[job, machine].start for job in range(num_jobs)]\n",
198+
" ends = [tasks[job, machine].end for job in range(num_jobs)]\n",
199+
"\n",
200+
" for idx1, idx2 in product(range(num_jobs), repeat=2):\n",
201+
" if idx1 == idx2:\n",
202+
" continue\n",
203+
"\n",
204+
" # Since all machines share the same arc literals, if the literal\n",
205+
" # i -> j is True, this enforces that job i is always scheduled\n",
206+
" # before job j on all machines.\n",
207+
" lit = lits[idx1, idx2]\n",
208+
" m.add(ends[idx1] <= starts[idx2]).only_enforce_if(lit)\n",
209+
"\n",
210+
" # Set minimizing makespan as objective.\n",
211+
" obj_var = m.new_int_var(0, horizon, \"makespan\")\n",
212+
" completion_times = [\n",
213+
" tasks[(job, num_machines - 1)].end for job in range(num_jobs)\n",
214+
" ]\n",
215+
" m.add_max_equality(obj_var, completion_times)\n",
216+
" m.minimize(obj_var)\n",
217+
"\n",
218+
" solver = cp_model.CpSolver()\n",
219+
" if params:\n",
220+
" text_format.Parse(params, solver.parameters)\n",
221+
" solver.parameters.log_search_progress = log\n",
222+
" solver.parameters.max_time_in_seconds = time_limit\n",
223+
"\n",
224+
" status_code = solver.Solve(m)\n",
225+
" status = solver.StatusName(status_code)\n",
226+
"\n",
227+
" print(f\"Status: {status}\")\n",
228+
" print(f\"Makespan: {solver.ObjectiveValue()}\")\n",
229+
"\n",
230+
" if status in [\"OPTIMAL\", \"FEASIBLE\"]:\n",
231+
" start = [solver.Value(tasks[job, 0].start) for job in range(num_jobs)]\n",
232+
" solution = np.argsort(start) + 1\n",
233+
" print(f\"Solution: {solution}\")\n",
234+
"\n",
235+
"\n",
236+
"def main(argv: Sequence[str]) -> None:\n",
237+
" \"\"\"Creates the data and calls the solving procedure.\"\"\"\n",
238+
" # VRF_10_5_2 instance from http://soa.iti.es/problem-instances.\n",
239+
" # Optimal makespan is 698.\n",
240+
" processing_times = [\n",
241+
" [79, 67, 10, 48, 52],\n",
242+
" [40, 40, 57, 21, 54],\n",
243+
" [48, 93, 49, 11, 79],\n",
244+
" [16, 23, 19, 2, 38],\n",
245+
" [38, 90, 57, 73, 3],\n",
246+
" [76, 13, 99, 98, 55],\n",
247+
" [73, 85, 40, 20, 85],\n",
248+
" [34, 6, 27, 53, 21],\n",
249+
" [38, 6, 35, 28, 44],\n",
250+
" [32, 11, 11, 34, 27],\n",
251+
" ]\n",
252+
"\n",
253+
" permutation_flow_shop(\n",
254+
" np.array(processing_times), _TIME_LIMIT.value, _LOG.value, _PARAMS.value\n",
255+
" )\n",
256+
"\n",
257+
"\n",
258+
"app.run(main) \n",
259+
"\n"
260+
]
261+
}
262+
],
263+
"metadata": {},
264+
"nbformat": 4,
265+
"nbformat_minor": 5
266+
}

examples/notebook/constraint_solver/cvrp_reload.ipynb renamed to examples/notebook/routing/cvrp_reload.ipynb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@
4141
"source": [
4242
"<table align=\"left\">\n",
4343
"<td>\n",
44-
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/constraint_solver/cvrp_reload.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
44+
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/routing/cvrp_reload.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
4545
"</td>\n",
4646
"<td>\n",
47-
"<a href=\"https://github.com/google/or-tools/blob/main/ortools/constraint_solver/samples/cvrp_reload.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
47+
"<a href=\"https://github.com/google/or-tools/blob/main/ortools/routing/samples/cvrp_reload.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
4848
"</td>\n",
4949
"</table>"
5050
]
@@ -111,8 +111,8 @@
111111
"source": [
112112
"from functools import partial\n",
113113
"\n",
114-
"from ortools.constraint_solver import pywrapcp\n",
115114
"from ortools.routing import enums_pb2\n",
115+
"from ortools.routing import pywraprouting\n",
116116
"\n",
117117
"\n",
118118
"###########################\n",
@@ -439,12 +439,12 @@
439439
" data = create_data_model()\n",
440440
"\n",
441441
" # Create the routing index manager\n",
442-
" manager = pywrapcp.RoutingIndexManager(\n",
442+
" manager = pywraprouting.RoutingIndexManager(\n",
443443
" data[\"num_locations\"], data[\"num_vehicles\"], data[\"depot\"]\n",
444444
" )\n",
445445
"\n",
446446
" # Create Routing Model\n",
447-
" routing = pywrapcp.RoutingModel(manager)\n",
447+
" routing = pywraprouting.RoutingModel(manager)\n",
448448
"\n",
449449
" # Define weight of each edge\n",
450450
" distance_evaluator_index = routing.RegisterTransitCallback(\n",
@@ -468,7 +468,7 @@
468468
" add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
469469
"\n",
470470
" # Setting first solution heuristic (cheapest addition).\n",
471-
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
471+
" search_parameters = pywraprouting.DefaultRoutingSearchParameters()\n",
472472
" search_parameters.first_solution_strategy = (\n",
473473
" enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
474474
" ) # pylint: disable=no-member\n",

examples/notebook/constraint_solver/cvrptw_break.ipynb renamed to examples/notebook/routing/cvrptw_break.ipynb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@
4141
"source": [
4242
"<table align=\"left\">\n",
4343
"<td>\n",
44-
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/constraint_solver/cvrptw_break.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
44+
"<a href=\"https://colab.research.google.com/github/google/or-tools/blob/main/examples/notebook/routing/cvrptw_break.ipynb\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/colab_32px.png\"/>Run in Google Colab</a>\n",
4545
"</td>\n",
4646
"<td>\n",
47-
"<a href=\"https://github.com/google/or-tools/blob/main/ortools/constraint_solver/samples/cvrptw_break.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
47+
"<a href=\"https://github.com/google/or-tools/blob/main/ortools/routing/samples/cvrptw_break.py\"><img src=\"https://raw.githubusercontent.com/google/or-tools/main/tools/github_32px.png\"/>View source on GitHub</a>\n",
4848
"</td>\n",
4949
"</table>"
5050
]
@@ -92,8 +92,8 @@
9292
"outputs": [],
9393
"source": [
9494
"import functools\n",
95-
"from ortools.constraint_solver import pywrapcp\n",
9695
"from ortools.routing import enums_pb2\n",
96+
"from ortools.routing import pywraprouting\n",
9797
"\n",
9898
"\n",
9999
"def create_data_model():\n",
@@ -347,12 +347,12 @@
347347
" data = create_data_model()\n",
348348
"\n",
349349
" # Create the routing index manager\n",
350-
" manager = pywrapcp.RoutingIndexManager(\n",
350+
" manager = pywraprouting.RoutingIndexManager(\n",
351351
" data[\"numlocations_\"], data[\"num_vehicles\"], data[\"depot\"]\n",
352352
" )\n",
353353
"\n",
354354
" # Create Routing Model\n",
355-
" routing = pywrapcp.RoutingModel(manager)\n",
355+
" routing = pywraprouting.RoutingModel(manager)\n",
356356
"\n",
357357
" # Define weight of each edge\n",
358358
" distance_evaluator_index = routing.RegisterTransitCallback(\n",
@@ -398,7 +398,7 @@
398398
" )\n",
399399
"\n",
400400
" # Setting first solution heuristic (cheapest addition).\n",
401-
" search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
401+
" search_parameters = pywraprouting.DefaultRoutingSearchParameters()\n",
402402
" search_parameters.first_solution_strategy = (\n",
403403
" enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC\n",
404404
" ) # pylint: disable=no-member\n",

0 commit comments

Comments
 (0)