Update examples/notebook
generated using ./tools/gen_all_notebook.sh
This commit is contained in:
77
examples/notebook/algorithms/knapsack.ipynb
Normal file
77
examples/notebook/algorithms/knapsack.ipynb
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"\"\"\"A simple knapsack problem.\"\"\"\n",
|
||||
"# [START program]\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.algorithms import pywrapknapsack_solver\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"# [START solver]\n",
|
||||
"solver = pywrapknapsack_solver.KnapsackSolver(\n",
|
||||
" pywrapknapsack_solver.KnapsackSolver.\n",
|
||||
" KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, 'KnapsackExample')\n",
|
||||
"# [END solver]\n",
|
||||
"\n",
|
||||
"# [START data]\n",
|
||||
"values = [\n",
|
||||
" 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147,\n",
|
||||
" 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28,\n",
|
||||
" 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276,\n",
|
||||
" 312\n",
|
||||
"]\n",
|
||||
"weights = [[\n",
|
||||
" 7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0,\n",
|
||||
" 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71,\n",
|
||||
" 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13\n",
|
||||
"]]\n",
|
||||
"capacities = [850]\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# [START solve]\n",
|
||||
"solver.Init(values, weights, capacities)\n",
|
||||
"computed_value = solver.Solve()\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# [START print_solution]\n",
|
||||
"packed_items = []\n",
|
||||
"packed_weights = []\n",
|
||||
"total_weight = 0\n",
|
||||
"print('Total value =', computed_value)\n",
|
||||
"for i in range(len(values)):\n",
|
||||
" if solver.BestSolutionContains(i):\n",
|
||||
" packed_items.append(i)\n",
|
||||
" packed_weights.append(weights[0][i])\n",
|
||||
" total_weight += weights[0][i]\n",
|
||||
"print('Total weight:', total_weight)\n",
|
||||
"print('Packed items:', packed_items)\n",
|
||||
"print('Packed_weights:', packed_weights)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
67
examples/notebook/algorithms/simple_knapsack_program.ipynb
Normal file
67
examples/notebook/algorithms/simple_knapsack_program.ipynb
Normal file
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"A simple knapsack problem.\"\"\"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.algorithms import pywrapknapsack_solver\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"# [START solver]\n",
|
||||
"solver = pywrapknapsack_solver.KnapsackSolver(\n",
|
||||
" pywrapknapsack_solver.KnapsackSolver.\n",
|
||||
" KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER, \"test\")\n",
|
||||
"# [END solver]\n",
|
||||
"\n",
|
||||
"# [START data]\n",
|
||||
"weights = [[\n",
|
||||
" 565, 406, 194, 130, 435, 367, 230, 315, 393, 125, 670, 892, 600, 293,\n",
|
||||
" 712, 147, 421, 255\n",
|
||||
"]]\n",
|
||||
"capacities = [850]\n",
|
||||
"values = weights[0]\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# [START solve]\n",
|
||||
"solver.Init(values, weights, capacities)\n",
|
||||
"computed_value = solver.Solve()\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# [START print_solution]\n",
|
||||
"packed_items = [\n",
|
||||
" x for x in range(0, len(weights[0])) if solver.BestSolutionContains(x)\n",
|
||||
"]\n",
|
||||
"packed_weights = [weights[0][i] for i in packed_items]\n",
|
||||
"\n",
|
||||
"print(\"Packed items: \", packed_items)\n",
|
||||
"print(\"Packed weights: \", packed_weights)\n",
|
||||
"print(\"Total weight (same as total value): \", computed_value)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2017 Google\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",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Data.\n",
|
||||
"cost = [[90, 76, 75, 70, 50, 74], [35, 85, 55, 65, 48,\n",
|
||||
" 101], [125, 95, 90, 105, 59, 120],\n",
|
||||
" [45, 110, 95, 115, 104, 83], [60, 105, 80, 75, 59, 62], [\n",
|
||||
" 45, 65, 110, 95, 47, 31\n",
|
||||
" ], [38, 51, 107, 41, 69, 99], [47, 85, 57, 71,\n",
|
||||
" 92, 77], [39, 63, 97, 49, 118, 56],\n",
|
||||
" [47, 101, 71, 60, 88, 109], [17, 39, 103, 64, 61,\n",
|
||||
" 92], [101, 45, 83, 59, 92, 27]]\n",
|
||||
"\n",
|
||||
"group1 = [\n",
|
||||
" [0, 0, 1, 1], # Workers 2, 3\n",
|
||||
" [0, 1, 0, 1], # Workers 1, 3\n",
|
||||
" [0, 1, 1, 0], # Workers 1, 2\n",
|
||||
" [1, 1, 0, 0], # Workers 0, 1\n",
|
||||
" [1, 0, 1, 0]\n",
|
||||
"] # Workers 0, 2\n",
|
||||
"\n",
|
||||
"group2 = [\n",
|
||||
" [0, 0, 1, 1], # Workers 6, 7\n",
|
||||
" [0, 1, 0, 1], # Workers 5, 7\n",
|
||||
" [0, 1, 1, 0], # Workers 5, 6\n",
|
||||
" [1, 1, 0, 0], # Workers 4, 5\n",
|
||||
" [1, 0, 0, 1]\n",
|
||||
"] # Workers 4, 7\n",
|
||||
"\n",
|
||||
"group3 = [\n",
|
||||
" [0, 0, 1, 1], # Workers 10, 11\n",
|
||||
" [0, 1, 0, 1], # Workers 9, 11\n",
|
||||
" [0, 1, 1, 0], # Workers 9, 10\n",
|
||||
" [1, 0, 1, 0], # Workers 8, 10\n",
|
||||
" [1, 0, 0, 1]\n",
|
||||
"] # Workers 8, 11\n",
|
||||
"\n",
|
||||
"sizes = [10, 7, 3, 12, 15, 4, 11, 5]\n",
|
||||
"total_size_max = 15\n",
|
||||
"num_workers = len(cost)\n",
|
||||
"num_tasks = len(cost[1])\n",
|
||||
"all_workers = range(num_workers)\n",
|
||||
"all_tasks = range(num_tasks)\n",
|
||||
"\n",
|
||||
"# Model.\n",
|
||||
"\n",
|
||||
"model = cp_model.CpModel()\n",
|
||||
"# Variables\n",
|
||||
"total_cost = model.NewIntVar(0, 1000, 'total_cost')\n",
|
||||
"x = [[model.NewBoolVar('x[%i,%i]' % (i, j))\n",
|
||||
" for j in all_tasks]\n",
|
||||
" for i in all_workers]\n",
|
||||
"works = [model.NewBoolVar('works[%i]' % i) for i in all_workers]\n",
|
||||
"\n",
|
||||
"# Constraints\n",
|
||||
"\n",
|
||||
"# Link x and workers.\n",
|
||||
"for i in range(num_workers):\n",
|
||||
" model.AddMaxEquality(works[i], x[i])\n",
|
||||
"\n",
|
||||
"# Each task is assigned to at least one worker.\n",
|
||||
"for j in all_tasks:\n",
|
||||
" model.Add(sum(x[i][j] for i in all_workers) >= 1)\n",
|
||||
"\n",
|
||||
"# Total task size for each worker is at most total_size_max\n",
|
||||
"for i in all_workers:\n",
|
||||
" model.Add(sum(sizes[j] * x[i][j] for j in all_tasks) <= total_size_max)\n",
|
||||
"\n",
|
||||
"# Group constraints.\n",
|
||||
"model.AddAllowedAssignments([works[0], works[1], works[2], works[3]], group1)\n",
|
||||
"model.AddAllowedAssignments([works[4], works[5], works[6], works[7]], group2)\n",
|
||||
"model.AddAllowedAssignments([works[8], works[9], works[10], works[11]],\n",
|
||||
" group3)\n",
|
||||
"\n",
|
||||
"# Total cost\n",
|
||||
"model.Add(total_cost == sum(\n",
|
||||
" x[i][j] * cost[i][j] for j in all_tasks for i in all_workers))\n",
|
||||
"model.Minimize(total_cost)\n",
|
||||
"\n",
|
||||
"# Solve and output solution.\n",
|
||||
"solver = cp_model.CpSolver()\n",
|
||||
"status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
"if status == cp_model.OPTIMAL:\n",
|
||||
" print('Total cost = %i' % solver.ObjectiveValue())\n",
|
||||
" print()\n",
|
||||
" for i in all_workers:\n",
|
||||
" for j in all_tasks:\n",
|
||||
" if solver.Value(x[i][j]) == 1:\n",
|
||||
" print('Worker ', i, ' assigned to task ', j, ' Cost = ', cost[i][j])\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('Statistics')\n",
|
||||
"print(' - conflicts : %i' % solver.NumConflicts())\n",
|
||||
"print(' - branches : %i' % solver.NumBranches())\n",
|
||||
"print(' - wall time : %f ms' % solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2017 Google\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",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"num_groups = 11\n",
|
||||
"num_values = 121\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
"boo_x_i_j = {}\n",
|
||||
"for i in range(num_values):\n",
|
||||
" for j in range(num_groups):\n",
|
||||
" boo_x_i_j[(i, j)] = model.NewBoolVar('x%d belongs to group %d' % (i, j))\n",
|
||||
"\n",
|
||||
"e = model.NewIntVar(0, 5, 'epsilon')\n",
|
||||
"\n",
|
||||
"values = [i + 1 + 3 * (i > 99) for i in range(num_values)]\n",
|
||||
"sum_of_values = sum(values)\n",
|
||||
"average_value = sum_of_values / num_groups\n",
|
||||
"\n",
|
||||
"for j in range(num_groups):\n",
|
||||
" model.Add(sum(boo_x_i_j[(i, j)]\n",
|
||||
" for i in range(num_values)) == num_values / num_groups)\n",
|
||||
"\n",
|
||||
"for i in range(num_values):\n",
|
||||
" model.Add(sum(boo_x_i_j[(i, j)] for j in range(num_groups)) == 1)\n",
|
||||
"\n",
|
||||
"for j in range(num_groups):\n",
|
||||
" model.Add(sum(boo_x_i_j[(i, j)] * values[i] for i in range(num_values)) -\n",
|
||||
" average_value <= e)\n",
|
||||
" model.Add(sum(boo_x_i_j[(i, j)] * values[i] for i in range(num_values)) -\n",
|
||||
" average_value >= -e)\n",
|
||||
"\n",
|
||||
"model.Minimize(e)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"solver = cp_model.CpSolver()\n",
|
||||
"status = solver.Solve(model)\n",
|
||||
"print('Optimal epsilon: %i' % solver.ObjectiveValue())\n",
|
||||
"print('Statistics')\n",
|
||||
"print(' - conflicts : %i' % solver.NumConflicts())\n",
|
||||
"print(' - branches : %i' % solver.NumBranches())\n",
|
||||
"print(' - wall time : %f s' % solver.WallTime())\n",
|
||||
"\n",
|
||||
"groups = {}\n",
|
||||
"for j in range(num_groups):\n",
|
||||
" groups[j] = []\n",
|
||||
"for i in range(num_values):\n",
|
||||
" for j in range(num_groups):\n",
|
||||
" if solver.Value(boo_x_i_j[(i, j)]):\n",
|
||||
" groups[j].append(values[i])\n",
|
||||
"\n",
|
||||
"for j in range(num_groups):\n",
|
||||
" print ('group %i: average = %0.2f [' % (\n",
|
||||
" j, 1.0 * sum(groups[j]) / len(groups[j])), end='')\n",
|
||||
" for v in groups[j]:\n",
|
||||
" print(' %i' % v, end='')\n",
|
||||
" print(' ]')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2017 Google\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",
|
||||
"\"\"\"SAT code samples used in documentation.\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import absolute_import\n",
|
||||
"from __future__ import division\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"import collections\n",
|
||||
"\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def CodeSample():\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" x = model.NewBoolVar('x')\n",
|
||||
" print(x)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def LiteralSample():\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" x = model.NewBoolVar('x')\n",
|
||||
" not_x = x.Not()\n",
|
||||
" print(x)\n",
|
||||
" print(not_x)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def BoolOrSample():\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" x = model.NewBoolVar('x')\n",
|
||||
" y = model.NewBoolVar('y')\n",
|
||||
"\n",
|
||||
" model.AddBoolOr([x, y.Not()])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def ReifiedSample():\n",
|
||||
" \"\"\"Showcase creating a reified constraint.\"\"\"\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" x = model.NewBoolVar('x')\n",
|
||||
" y = model.NewBoolVar('y')\n",
|
||||
" b = model.NewBoolVar('b')\n",
|
||||
"\n",
|
||||
" # First version using a half-reified bool and.\n",
|
||||
" model.AddBoolAnd([x, y.Not()]).OnlyEnforceIf(b)\n",
|
||||
"\n",
|
||||
" # Second version using implications.\n",
|
||||
" model.AddImplication(b, x)\n",
|
||||
" model.AddImplication(b, y.Not())\n",
|
||||
"\n",
|
||||
" # Third version using bool or.\n",
|
||||
" model.AddBoolOr([b.Not(), x])\n",
|
||||
" model.AddBoolOr([b.Not(), y.Not()])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def RabbitsAndPheasants():\n",
|
||||
" \"\"\"Solves the rabbits + pheasants problem.\"\"\"\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" r = model.NewIntVar(0, 100, 'r')\n",
|
||||
" p = model.NewIntVar(0, 100, 'p')\n",
|
||||
"\n",
|
||||
" # 20 heads.\n",
|
||||
" model.Add(r + p == 20)\n",
|
||||
" # 56 legs.\n",
|
||||
" model.Add(4 * r + 2 * p == 56)\n",
|
||||
"\n",
|
||||
" # Solves and prints out the solution.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.FEASIBLE:\n",
|
||||
" print('%i rabbits and %i pheasants' % (solver.Value(r), solver.Value(p)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def BinpackingProblem():\n",
|
||||
" \"\"\"Solves a bin-packing problem.\"\"\"\n",
|
||||
" # Data.\n",
|
||||
" bin_capacity = 100\n",
|
||||
" slack_capacity = 20\n",
|
||||
" num_bins = 10\n",
|
||||
" all_bins = range(num_bins)\n",
|
||||
"\n",
|
||||
" items = [(20, 12), (15, 12), (30, 8), (45, 5)]\n",
|
||||
" num_items = len(items)\n",
|
||||
" all_items = range(num_items)\n",
|
||||
"\n",
|
||||
" # Model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" # Main variables.\n",
|
||||
" x = {}\n",
|
||||
" for i in all_items:\n",
|
||||
" num_copies = items[i][1]\n",
|
||||
" for b in all_bins:\n",
|
||||
" x[(i, b)] = model.NewIntVar(0, num_copies, 'x_%i_%i' % (i, b))\n",
|
||||
"\n",
|
||||
" # Load variables.\n",
|
||||
" load = [model.NewIntVar(0, bin_capacity, 'load_%i' % b) for b in all_bins]\n",
|
||||
"\n",
|
||||
" # Slack variables.\n",
|
||||
" slacks = [model.NewBoolVar('slack_%i' % b) for b in all_bins]\n",
|
||||
"\n",
|
||||
" # Links load and x.\n",
|
||||
" for b in all_bins:\n",
|
||||
" model.Add(load[b] == sum(x[(i, b)] * items[i][0] for i in all_items))\n",
|
||||
"\n",
|
||||
" # Place all items.\n",
|
||||
" for i in all_items:\n",
|
||||
" model.Add(sum(x[(i, b)] for b in all_bins) == items[i][1])\n",
|
||||
"\n",
|
||||
" # Links load and slack through an equivalence relation.\n",
|
||||
" safe_capacity = bin_capacity - slack_capacity\n",
|
||||
" for b in all_bins:\n",
|
||||
" # slack[b] => load[b] <= safe_capacity.\n",
|
||||
" model.Add(load[b] <= safe_capacity).OnlyEnforceIf(slacks[b])\n",
|
||||
" # not(slack[b]) => load[b] > safe_capacity.\n",
|
||||
" model.Add(load[b] > safe_capacity).OnlyEnforceIf(slacks[b].Not())\n",
|
||||
"\n",
|
||||
" # Maximize sum of slacks.\n",
|
||||
" model.Maximize(sum(slacks))\n",
|
||||
"\n",
|
||||
" # Solves and prints out the solution.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
" print('Solve status: %s' % solver.StatusName(status))\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" print('Optimal objective value: %i' % solver.ObjectiveValue())\n",
|
||||
" print('Statistics')\n",
|
||||
" print(' - conflicts : %i' % solver.NumConflicts())\n",
|
||||
" print(' - branches : %i' % solver.NumBranches())\n",
|
||||
" print(' - wall time : %f s' % solver.WallTime())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def IntervalSample():\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" horizon = 100\n",
|
||||
" start_var = model.NewIntVar(0, horizon, 'start')\n",
|
||||
" duration = 10 # Python cp/sat code accept integer variables or constants.\n",
|
||||
" end_var = model.NewIntVar(0, horizon, 'end')\n",
|
||||
" interval_var = model.NewIntervalVar(start_var, duration, end_var, 'interval')\n",
|
||||
" print('start = %s, duration = %i, end = %s, interval = %s' %\n",
|
||||
" (start_var, duration, end_var, interval_var))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def OptionalIntervalSample():\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" horizon = 100\n",
|
||||
" start_var = model.NewIntVar(0, horizon, 'start')\n",
|
||||
" duration = 10 # Python cp/sat code accept integer variables or constants.\n",
|
||||
" end_var = model.NewIntVar(0, horizon, 'end')\n",
|
||||
" presence_var = model.NewBoolVar('presence')\n",
|
||||
" interval_var = model.NewOptionalIntervalVar(start_var, duration, end_var,\n",
|
||||
" presence_var, 'interval')\n",
|
||||
" print('start = %s, duration = %i, end = %s, presence = %s, interval = %s' %\n",
|
||||
" (start_var, duration, end_var, presence_var, interval_var))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSat():\n",
|
||||
" \"\"\"Minimal CP-SAT example to showcase calling the solver.\"\"\"\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" # Creates the 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",
|
||||
" # Creates the constraints.\n",
|
||||
" model.Add(x != y)\n",
|
||||
"\n",
|
||||
" # Creates a solver and solves the model.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.FEASIBLE:\n",
|
||||
" print('x = %i' % solver.Value(x))\n",
|
||||
" print('y = %i' % solver.Value(y))\n",
|
||||
" print('z = %i' % solver.Value(z))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSatWithTimeLimit():\n",
|
||||
" \"\"\"Minimal CP-SAT example to showcase calling the solver.\"\"\"\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" # Creates the 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",
|
||||
" # Adds an all-different constraint.\n",
|
||||
" model.Add(x != y)\n",
|
||||
"\n",
|
||||
" # Creates a solver and solves the model.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
"\n",
|
||||
" # Sets a time limit of 10 seconds.\n",
|
||||
" solver.parameters.max_time_in_seconds = 10.0\n",
|
||||
"\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.FEASIBLE:\n",
|
||||
" print('x = %i' % solver.Value(x))\n",
|
||||
" print('y = %i' % solver.Value(y))\n",
|
||||
" print('z = %i' % solver.Value(z))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# You need to subclass the cp_model.CpSolverSolutionCallback class.\n",
|
||||
"class VarArrayAndObjectiveSolutionPrinter(cp_model.CpSolverSolutionCallback):\n",
|
||||
" \"\"\"Print intermediate solutions.\"\"\"\n",
|
||||
"\n",
|
||||
" def __init__(self, variables):\n",
|
||||
" cp_model.CpSolverSolutionCallback.__init__(self)\n",
|
||||
" self.__variables = variables\n",
|
||||
" self.__solution_count = 0\n",
|
||||
"\n",
|
||||
" def OnSolutionCallback(self):\n",
|
||||
" print('Solution %i' % self.__solution_count)\n",
|
||||
" print(' objective value = %i' % self.ObjectiveValue())\n",
|
||||
" for v in self.__variables:\n",
|
||||
" print(' %s = %i' % (v, self.Value(v)), end=' ')\n",
|
||||
" print()\n",
|
||||
" self.__solution_count += 1\n",
|
||||
"\n",
|
||||
" def SolutionCount(self):\n",
|
||||
" return self.__solution_count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSatPrintIntermediateSolutions():\n",
|
||||
" \"\"\"Showcases printing intermediate solutions found during search.\"\"\"\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" # Creates the 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",
|
||||
" # Creates the constraints.\n",
|
||||
" model.Add(x != y)\n",
|
||||
" model.Maximize(x + 2 * y + 3 * z)\n",
|
||||
"\n",
|
||||
" # Creates a solver and solves.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" solution_printer = VarArrayAndObjectiveSolutionPrinter([x, y, z])\n",
|
||||
" status = solver.SolveWithSolutionCallback(model, solution_printer)\n",
|
||||
"\n",
|
||||
" print('Status = %s' % solver.StatusName(status))\n",
|
||||
" print('Number of solutions found: %i' % solution_printer.SolutionCount())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):\n",
|
||||
" \"\"\"Print intermediate solutions.\"\"\"\n",
|
||||
"\n",
|
||||
" def __init__(self, variables):\n",
|
||||
" cp_model.CpSolverSolutionCallback.__init__(self)\n",
|
||||
" self.__variables = variables\n",
|
||||
" self.__solution_count = 0\n",
|
||||
"\n",
|
||||
" def OnSolutionCallback(self):\n",
|
||||
" self.__solution_count += 1\n",
|
||||
" for v in self.__variables:\n",
|
||||
" print('%s=%i' % (v, self.Value(v)), end=' ')\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" def SolutionCount(self):\n",
|
||||
" return self.__solution_count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSatAllSolutions():\n",
|
||||
" \"\"\"Showcases calling the solver to search for all solutions.\"\"\"\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
" # Creates the 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",
|
||||
" # Create the constraints.\n",
|
||||
" model.Add(x != y)\n",
|
||||
"\n",
|
||||
" # Create a solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" solution_printer = VarArraySolutionPrinter([x, y, z])\n",
|
||||
" status = solver.SearchForAllSolutions(model, solution_printer)\n",
|
||||
" print('Status = %s' % solver.StatusName(status))\n",
|
||||
" print('Number of solutions found: %i' % solution_printer.SolutionCount())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def SolvingLinearProblem():\n",
|
||||
" \"\"\"CP-SAT linear solver problem.\"\"\"\n",
|
||||
" # Create a model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" # x and y are integer non-negative variables.\n",
|
||||
" x = model.NewIntVar(0, 17, 'x')\n",
|
||||
" y = model.NewIntVar(0, 17, 'y')\n",
|
||||
" model.Add(2 * x + 14 * y <= 35)\n",
|
||||
" model.Add(2 * x <= 7)\n",
|
||||
" obj_var = model.NewIntVar(0, 1000, 'obj_var')\n",
|
||||
" model.Add(obj_var == x + 10 * y)\n",
|
||||
" model.Maximize(obj_var)\n",
|
||||
"\n",
|
||||
" # Create a solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" print('Objective value: %i' % solver.ObjectiveValue())\n",
|
||||
" print()\n",
|
||||
" print('x= %i' % solver.Value(x))\n",
|
||||
" print('y= %i' % solver.Value(y))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalJobShop():\n",
|
||||
" \"\"\"Minimal jobshop problem.\"\"\"\n",
|
||||
" # Create the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" machines_count = 3\n",
|
||||
" jobs_count = 3\n",
|
||||
" all_machines = range(0, machines_count)\n",
|
||||
" all_jobs = range(0, jobs_count)\n",
|
||||
" # Define data.\n",
|
||||
" machines = [[0, 1, 2], [0, 2, 1], [1, 2]]\n",
|
||||
"\n",
|
||||
" processing_times = [[3, 2, 2], [2, 1, 4], [4, 3]]\n",
|
||||
" # Computes horizon.\n",
|
||||
" horizon = 0\n",
|
||||
" for job in all_jobs:\n",
|
||||
" horizon += sum(processing_times[job])\n",
|
||||
"\n",
|
||||
" task_type = collections.namedtuple('task_type', 'start end interval')\n",
|
||||
" assigned_task_type = collections.namedtuple('assigned_task_type',\n",
|
||||
" 'start job index')\n",
|
||||
"\n",
|
||||
" # Creates jobs.\n",
|
||||
" all_tasks = {}\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job])):\n",
|
||||
" start_var = model.NewIntVar(0, horizon, 'start_%i_%i' % (job, index))\n",
|
||||
" duration = processing_times[job][index]\n",
|
||||
" end_var = model.NewIntVar(0, horizon, 'end_%i_%i' % (job, index))\n",
|
||||
" interval_var = model.NewIntervalVar(start_var, duration, end_var,\n",
|
||||
" 'interval_%i_%i' % (job, index))\n",
|
||||
" all_tasks[(job, index)] = task_type(\n",
|
||||
" start=start_var, end=end_var, interval=interval_var)\n",
|
||||
"\n",
|
||||
" # Creates sequence variables and add disjunctive constraints.\n",
|
||||
" for machine in all_machines:\n",
|
||||
" intervals = []\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job])):\n",
|
||||
" if machines[job][index] == machine:\n",
|
||||
" intervals.append(all_tasks[(job, index)].interval)\n",
|
||||
" model.AddNoOverlap(intervals)\n",
|
||||
"\n",
|
||||
" # Add precedence contraints.\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job]) - 1):\n",
|
||||
" model.Add(all_tasks[(job, index + 1)].start >= all_tasks[(job,\n",
|
||||
" index)].end)\n",
|
||||
"\n",
|
||||
" # Makespan objective.\n",
|
||||
" obj_var = model.NewIntVar(0, horizon, 'makespan')\n",
|
||||
" model.AddMaxEquality(\n",
|
||||
" obj_var,\n",
|
||||
" [all_tasks[(job, len(machines[job]) - 1)].end for job in all_jobs])\n",
|
||||
" model.Minimize(obj_var)\n",
|
||||
"\n",
|
||||
" # Solve model.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" # Print out makespan.\n",
|
||||
" print('Optimal Schedule Length: %i' % solver.ObjectiveValue())\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" # Create one list of assigned tasks per machine.\n",
|
||||
" assigned_jobs = [[] for _ in range(machines_count)]\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(len(machines[job])):\n",
|
||||
" machine = machines[job][index]\n",
|
||||
" assigned_jobs[machine].append(\n",
|
||||
" assigned_task_type(\n",
|
||||
" start=solver.Value(all_tasks[(job, index)].start),\n",
|
||||
" job=job,\n",
|
||||
" index=index))\n",
|
||||
"\n",
|
||||
" disp_col_width = 10\n",
|
||||
" sol_line = ''\n",
|
||||
" sol_line_tasks = ''\n",
|
||||
"\n",
|
||||
" print('Optimal Schedule', '\\n')\n",
|
||||
"\n",
|
||||
" for machine in all_machines:\n",
|
||||
" # Sort by starting time.\n",
|
||||
" assigned_jobs[machine].sort()\n",
|
||||
" sol_line += 'Machine ' + str(machine) + ': '\n",
|
||||
" sol_line_tasks += 'Machine ' + str(machine) + ': '\n",
|
||||
"\n",
|
||||
" for assigned_task in assigned_jobs[machine]:\n",
|
||||
" name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)\n",
|
||||
" # Add spaces to output to align columns.\n",
|
||||
" sol_line_tasks += name + ' ' * (disp_col_width - len(name))\n",
|
||||
" start = assigned_task.start\n",
|
||||
" duration = processing_times[assigned_task.job][assigned_task.index]\n",
|
||||
"\n",
|
||||
" sol_tmp = '[%i,%i]' % (start, start + duration)\n",
|
||||
" # Add spaces to output to align columns.\n",
|
||||
" sol_line += sol_tmp + ' ' * (disp_col_width - len(sol_tmp))\n",
|
||||
"\n",
|
||||
" sol_line += '\\n'\n",
|
||||
" sol_line_tasks += '\\n'\n",
|
||||
"\n",
|
||||
" print(sol_line_tasks)\n",
|
||||
" print('Time Intervals for task_types\\n')\n",
|
||||
" print(sol_line)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"print('--- CodeSample ---')\n",
|
||||
"CodeSample()\n",
|
||||
"print('--- LiteralSample ---')\n",
|
||||
"LiteralSample()\n",
|
||||
"print('--- BoolOrSample ---')\n",
|
||||
"BoolOrSample()\n",
|
||||
"print('--- ReifiedSample ---')\n",
|
||||
"ReifiedSample()\n",
|
||||
"print('--- RabbitsAndPheasants ---')\n",
|
||||
"RabbitsAndPheasants()\n",
|
||||
"print('--- BinpackingProblem ---')\n",
|
||||
"BinpackingProblem()\n",
|
||||
"print('--- IntervalSample ---')\n",
|
||||
"IntervalSample()\n",
|
||||
"print('--- OptionalIntervalSample ---')\n",
|
||||
"OptionalIntervalSample()\n",
|
||||
"print('--- MinimalCpSat ---')\n",
|
||||
"MinimalCpSat()\n",
|
||||
"print('--- MinimalCpSatWithTimeLimit ---')\n",
|
||||
"MinimalCpSatWithTimeLimit()\n",
|
||||
"print('--- MinimalCpSatPrintIntermediateSolutions ---')\n",
|
||||
"MinimalCpSatPrintIntermediateSolutions()\n",
|
||||
"print('--- MinimalCpSatAllSolutions ---')\n",
|
||||
"MinimalCpSatAllSolutions()\n",
|
||||
"print('--- SolvingLinearProblem ---')\n",
|
||||
"SolvingLinearProblem()\n",
|
||||
"print('--- MinimalJobShop ---')\n",
|
||||
"MinimalJobShop()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
206
examples/notebook/constraint_solver/cvrp.ipynb
Normal file
206
examples/notebook/constraint_solver/cvrp.ipynb
Normal file
@@ -0,0 +1,206 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"# 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",
|
||||
"\"\"\"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",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"from six.moves import xrange\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"def create_data_model():\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",
|
||||
" (0, 1), (1, 1),\n",
|
||||
" (5, 2), (7, 2),\n",
|
||||
" (3, 3), (6, 3),\n",
|
||||
" (5, 5), (8, 5),\n",
|
||||
" (1, 6), (2, 6),\n",
|
||||
" (3, 7), (6, 7),\n",
|
||||
" (0, 8), (7, 8)]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # 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['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",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['vehicle_capacity'] = 15\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\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",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" else:\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\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",
|
||||
"\n",
|
||||
" return demand_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacity'],\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" capacity)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, routing, manager, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie('Capacity')\n",
|
||||
" for vehicle_id in xrange(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" plan_output += ' {} Load({}) -> '.format(\n",
|
||||
" manager.IndexToNode(index), assignment.Value(load_var))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" vehicle_id)\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" plan_output += ' {0} Load({1})\\n'.format(\n",
|
||||
" manager.IndexToNode(index), assignment.Value(load_var))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(distance)\n",
|
||||
" plan_output += 'Load of the route: {}\\n'.format(\n",
|
||||
" assignment.Value(load_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" total_load += assignment.Value(load_var)\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" print('Total Load of all routes: {}'.format(total_load))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_distance_evaluator(data), manager))\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator)\n",
|
||||
"\n",
|
||||
"# Add Capacity constraint\n",
|
||||
"demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" partial(create_demand_evaluator(data), manager))\n",
|
||||
"add_capacity_constraints(routing, data, demand_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# Solve the problem.\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, routing, manager, assignment)\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
362
examples/notebook/constraint_solver/cvrp_reload.ipynb
Normal file
362
examples/notebook/constraint_solver/cvrp_reload.ipynb
Normal file
@@ -0,0 +1,362 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"# 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",
|
||||
"\"\"\"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",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"from six.moves import xrange\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"def create_data_model():\n",
|
||||
" \"\"\"Stores the data for the problem\"\"\"\n",
|
||||
" data = {}\n",
|
||||
" _capacity = 15\n",
|
||||
" # Locations in block unit\n",
|
||||
" _locations = [\n",
|
||||
" (4, 4), # depot\n",
|
||||
" (4, 4), # unload depot_prime\n",
|
||||
" (4, 4), # unload depot_second\n",
|
||||
" (4, 4), # unload depot_fourth\n",
|
||||
" (4, 4), # unload depot_fourth\n",
|
||||
" (4, 4), # unload depot_fifth\n",
|
||||
" (2, 0),\n",
|
||||
" (8, 0), # locations to visit\n",
|
||||
" (0, 1),\n",
|
||||
" (1, 1),\n",
|
||||
" (5, 2),\n",
|
||||
" (7, 2),\n",
|
||||
" (3, 3),\n",
|
||||
" (6, 3),\n",
|
||||
" (5, 5),\n",
|
||||
" (8, 5),\n",
|
||||
" (1, 6),\n",
|
||||
" (2, 6),\n",
|
||||
" (3, 7),\n",
|
||||
" (6, 7),\n",
|
||||
" (0, 8),\n",
|
||||
" (7, 8)\n",
|
||||
" ]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # 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['demands'] = \\\n",
|
||||
" [0, # depot\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\n",
|
||||
" -_capacity,\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['time_windows'] = \\\n",
|
||||
" [(0, 0), # depot\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (0, 1000),\n",
|
||||
" (75, 8500), (75, 8500), # 1, 2\n",
|
||||
" (60, 7000), (45, 5500), # 3, 4\n",
|
||||
" (0, 8000), (50, 6000), # 5, 6\n",
|
||||
" (0, 1000), (10, 2000), # 7, 8\n",
|
||||
" (0, 1000), (75, 8500), # 9, 10\n",
|
||||
" (85, 9500), (5, 1500), # 11, 12\n",
|
||||
" (15, 2500), (10, 2000), # 13, 14\n",
|
||||
" (45, 5500), (30, 4000)] # 15, 16\n",
|
||||
" data['num_vehicles'] = 3\n",
|
||||
" data['vehicle_capacity'] = _capacity\n",
|
||||
" data[\n",
|
||||
" 'vehicle_speed'] = 5 * 60 / 3.6 # Travel speed: 5km/h to convert in m/min\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\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 (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",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" else:\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_distance_dimension(routing, distance_evaluator_index):\n",
|
||||
" \"\"\"Add Global Span constraint\"\"\"\n",
|
||||
" distance = 'Distance'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" distance_evaluator_index,\n",
|
||||
" 0, # null slack\n",
|
||||
" 10000, # maximum distance per vehicle\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" distance)\n",
|
||||
" distance_dimension = routing.GetDimensionOrDie(distance)\n",
|
||||
" # Try to minimize the max distance among vehicles.\n",
|
||||
" # /!\\ It doesn't mean the standard deviation is minimized\n",
|
||||
" distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\n",
|
||||
" _demands = data['demands']\n",
|
||||
"\n",
|
||||
" def demand_evaluator(manager, from_node):\n",
|
||||
" \"\"\"Returns the demand of the current node\"\"\"\n",
|
||||
" return _demands[manager.IndexToNode(from_node)]\n",
|
||||
"\n",
|
||||
" return demand_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, manager, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" vehicle_capacity = data['vehicle_capacity']\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
" 0, # Null slack\n",
|
||||
" vehicle_capacity,\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" capacity)\n",
|
||||
"\n",
|
||||
" # Add Slack for reseting to zero unload depot nodes.\n",
|
||||
" # e.g. vehicle with load 10/15 arrives at node 1 (depot unload)\n",
|
||||
" # so we have CumulVar = 10(current load) + -15(unload) + 5(slack) = 0.\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie(capacity)\n",
|
||||
" for node_index in [1, 2, 3, 4, 5]:\n",
|
||||
" index = manager.NodeToIndex(node_index)\n",
|
||||
" capacity_dimension.SlackVar(index).SetRange(0, vehicle_capacity)\n",
|
||||
" routing.AddDisjunction([node_index], 0)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_time_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get total times between locations.\"\"\"\n",
|
||||
"\n",
|
||||
" def service_time(data, node):\n",
|
||||
" \"\"\"Gets the service time for the specified location.\"\"\"\n",
|
||||
" return abs(data['demands'][node]) * data['time_per_demand_unit']\n",
|
||||
"\n",
|
||||
" def travel_time(data, from_node, to_node):\n",
|
||||
" \"\"\"Gets the travel times between two locations.\"\"\"\n",
|
||||
" if from_node == to_node:\n",
|
||||
" travel_time = 0\n",
|
||||
" else:\n",
|
||||
" travel_time = manhattan_distance(data['locations'][\n",
|
||||
" from_node], data['locations'][to_node]) / data['vehicle_speed']\n",
|
||||
" return travel_time\n",
|
||||
"\n",
|
||||
" _total_time = {}\n",
|
||||
" # precompute total time to have time callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _total_time[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\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",
|
||||
"\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return time_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_time_window_constraints(routing, manager, data, time_evaluator):\n",
|
||||
" \"\"\"Add Time windows constraint\"\"\"\n",
|
||||
" time = 'Time'\n",
|
||||
" horizon = 1500\n",
|
||||
" routing.AddDimension(\n",
|
||||
" time_evaluator,\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",
|
||||
" 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",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n",
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Add time window constraints for each vehicle start node\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for vehicle_id in xrange(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",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" total_time = 0\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie('Capacity')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" dropped = []\n",
|
||||
" for order in xrange(0, routing.nodes()):\n",
|
||||
" index = manager.NodeToIndex(order)\n",
|
||||
" if assignment.Value(routing.NextVar(index)) == index:\n",
|
||||
" dropped.append(order)\n",
|
||||
" print('dropped orders: {}'.format(dropped))\n",
|
||||
"\n",
|
||||
" for vehicle_id in xrange(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += ' {0} Load({1}) Time({2},{3}) ->'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var), assignment.Max(time_var))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" vehicle_id)\n",
|
||||
" load_var = capacity_dimension.CumulVar(index)\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += ' {0} Load({1}) Time({2},{3})\\n'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var), assignment.Max(time_var))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(distance)\n",
|
||||
" plan_output += 'Load of the route: {}\\n'.format(\n",
|
||||
" assignment.Value(load_var))\n",
|
||||
" plan_output += 'Time of the route: {}min\\n'.format(\n",
|
||||
" assignment.Value(time_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" total_load += assignment.Value(load_var)\n",
|
||||
" total_time += assignment.Value(time_var)\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" print('Total Load of all routes: {}'.format(total_load))\n",
|
||||
" print('Total Time of all routes: {}min'.format(total_time))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_distance_evaluator(data), manager))\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add Distance constraint to minimize the longuest route\n",
|
||||
"add_distance_dimension(routing, distance_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add Capacity constraint\n",
|
||||
"demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" partial(create_demand_evaluator(data), manager))\n",
|
||||
"add_capacity_constraints(routing, manager, data, demand_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add Time Window constraint\n",
|
||||
"time_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_time_evaluator(data), manager))\n",
|
||||
"add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# Solve the problem.\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, manager, routing, assignment)\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
305
examples/notebook/constraint_solver/cvrptw.ipynb
Normal file
305
examples/notebook/constraint_solver/cvrptw.ipynb
Normal file
@@ -0,0 +1,305 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"# 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",
|
||||
"\"\"\"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",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters and time in minutes.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"from six.moves import xrange\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"def create_data_model():\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",
|
||||
" (0, 1), (1, 1),\n",
|
||||
" (5, 2), (7, 2),\n",
|
||||
" (3, 3), (6, 3),\n",
|
||||
" (5, 5), (8, 5),\n",
|
||||
" (1, 6), (2, 6),\n",
|
||||
" (3, 7), (6, 7),\n",
|
||||
" (0, 8), (7, 8)]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # 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['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",
|
||||
" 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",
|
||||
" data['time_per_demand_unit'] = 5 # 5 minutes/unit\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['vehicle_capacity'] = 15\n",
|
||||
" data['vehicle_speed'] = 83 # Travel speed: 5km/h converted in m/min\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\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",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" else:\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\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",
|
||||
"\n",
|
||||
" return demand_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacity'],\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" capacity)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_time_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get total times between locations.\"\"\"\n",
|
||||
"\n",
|
||||
" def service_time(data, node):\n",
|
||||
" \"\"\"Gets the service time for the specified location.\"\"\"\n",
|
||||
" return data['demands'][node] * data['time_per_demand_unit']\n",
|
||||
"\n",
|
||||
" def travel_time(data, from_node, to_node):\n",
|
||||
" \"\"\"Gets the travel times between two locations.\"\"\"\n",
|
||||
" 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",
|
||||
" return travel_time\n",
|
||||
"\n",
|
||||
" _total_time = {}\n",
|
||||
" # precompute total time to have time callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _total_time[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\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",
|
||||
"\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",
|
||||
" 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",
|
||||
" 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",
|
||||
" 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",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n",
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Add time window constraints for each vehicle start node\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for vehicle_id in xrange(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",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" total_time = 0\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie('Capacity')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" for vehicle_id in xrange(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\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}) Slack({4},{5}) ->'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var),\n",
|
||||
" 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",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" 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",
|
||||
" 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",
|
||||
" assignment.Value(load_var))\n",
|
||||
" plan_output += 'Time of the route: {}\\n'.format(\n",
|
||||
" assignment.Value(time_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" total_load += assignment.Value(load_var)\n",
|
||||
" total_time += assignment.Value(time_var)\n",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" 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",
|
||||
"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",
|
||||
"add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# Solve the problem.\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, manager, routing, assignment)\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
340
examples/notebook/constraint_solver/cvrptw_break.ipynb
Normal file
340
examples/notebook/constraint_solver/cvrptw_break.ipynb
Normal file
@@ -0,0 +1,340 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"# 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",
|
||||
"\"\"\"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",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters and time in minutes.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"from six.moves import xrange\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"def create_data_model():\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",
|
||||
" (0, 1), (1, 1),\n",
|
||||
" (5, 2), (7, 2),\n",
|
||||
" (3, 3), (6, 3),\n",
|
||||
" (5, 5), (8, 5),\n",
|
||||
" (1, 6), (2, 6),\n",
|
||||
" (3, 7), (6, 7),\n",
|
||||
" (0, 8), (7, 8)]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # 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['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",
|
||||
" 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",
|
||||
" 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",
|
||||
" data['vehicle_capacity'] = 15\n",
|
||||
" data['vehicle_speed'] = 83 # Travel speed: 5km/h converted in m/min\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\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",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" else:\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_demand_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get demands at each location.\"\"\"\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",
|
||||
"\n",
|
||||
" return demand_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_capacity_constraints(routing, data, demand_evaluator_index):\n",
|
||||
" \"\"\"Adds capacity constraint\"\"\"\n",
|
||||
" capacity = 'Capacity'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" demand_evaluator_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacity'],\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" capacity)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_time_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to get total times between locations.\"\"\"\n",
|
||||
"\n",
|
||||
" def service_time(data, node):\n",
|
||||
" \"\"\"Gets the service time for the specified location.\"\"\"\n",
|
||||
" return data['demands'][node] * data['time_per_demand_unit']\n",
|
||||
"\n",
|
||||
" def travel_time(data, from_node, to_node):\n",
|
||||
" \"\"\"Gets the travel times between two locations.\"\"\"\n",
|
||||
" 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",
|
||||
" return travel_time\n",
|
||||
"\n",
|
||||
" _total_time = {}\n",
|
||||
" # precompute total time to have time callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _total_time[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\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",
|
||||
"\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",
|
||||
" 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",
|
||||
" 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",
|
||||
" 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",
|
||||
" continue\n",
|
||||
" index = manager.NodeToIndex(location_idx)\n",
|
||||
" time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n",
|
||||
" routing.AddToAssignment(time_dimension.SlackVar(index))\n",
|
||||
" # Add time window constraints for each vehicle start node\n",
|
||||
" # and 'copy' the slack var in the solution object (aka Assignment) to print it\n",
|
||||
" for vehicle_id in xrange(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",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, manager, routing, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
"\n",
|
||||
" print('Breaks:')\n",
|
||||
" intervals = assignment.IntervalVarContainer()\n",
|
||||
" for i in xrange(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",
|
||||
" else:\n",
|
||||
" print('{}: Unperformed'.format(brk.Var().Name()))\n",
|
||||
"\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" total_time = 0\n",
|
||||
" capacity_dimension = routing.GetDimensionOrDie('Capacity')\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" for vehicle_id in xrange(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\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}) Slack({4},{5}) ->'.format(\n",
|
||||
" manager.IndexToNode(index),\n",
|
||||
" assignment.Value(load_var),\n",
|
||||
" assignment.Min(time_var),\n",
|
||||
" 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",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" 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",
|
||||
" 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",
|
||||
" assignment.Value(load_var))\n",
|
||||
" plan_output += 'Time of the route: {}\\n'.format(\n",
|
||||
" assignment.Value(time_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" total_load += assignment.Value(load_var)\n",
|
||||
" total_time += assignment.Value(time_var)\n",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" 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",
|
||||
"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",
|
||||
"add_time_window_constraints(routing, manager, data, time_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Add breaks\n",
|
||||
"time_dimension = routing.GetDimensionOrDie(\"Time\")\n",
|
||||
"node_visit_transit = {}\n",
|
||||
"for n in xrange(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",
|
||||
"\n",
|
||||
"break_intervals = {}\n",
|
||||
"#for v in xrange(data['num_vehicles']):\n",
|
||||
"for v in [0]:\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",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# Solve the problem.\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, manager, routing, assignment)\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
82
examples/notebook/constraint_solver/simple_cp_program.ipynb
Normal file
82
examples/notebook/constraint_solver/simple_cp_program.ipynb
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Constraint optimization example.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Entry point of the program.\"\"\"\n",
|
||||
"# Instantiate the solver.\n",
|
||||
"# [START solver]\n",
|
||||
"solver = pywrapcp.Solver('CPSimple')\n",
|
||||
"# [END solver]\n",
|
||||
"\n",
|
||||
"# Create the variables.\n",
|
||||
"# [START variables]\n",
|
||||
"num_vals = 3\n",
|
||||
"x = solver.IntVar(0, num_vals - 1, 'x')\n",
|
||||
"y = solver.IntVar(0, num_vals - 1, 'y')\n",
|
||||
"z = solver.IntVar(0, num_vals - 1, 'z')\n",
|
||||
"# [END variables]\n",
|
||||
"\n",
|
||||
"# Constraint 0: x != y.\n",
|
||||
"# [START constraints]\n",
|
||||
"solver.Add(x != y)\n",
|
||||
"print('Number of constraints: ', solver.Constraints())\n",
|
||||
"# [END constraints]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"decision_builder = solver.Phase([x, y, z], solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"count = 0\n",
|
||||
"solver.NewSearch(decision_builder)\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" count += 1\n",
|
||||
" solution = 'Solution {}:\\n'.format(count)\n",
|
||||
" for var in [x, y, z]:\n",
|
||||
" solution += ' {} = {}'.format(var.Name(), var.Value())\n",
|
||||
" print(solution)\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print('Number of solutions found: ', count)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n",
|
||||
"# [START advanced]\n",
|
||||
"print('Advanced usage:')\n",
|
||||
"print('Problem solved in ', solver.WallTime(), 'ms')\n",
|
||||
"print('Memory usage: ', pywrapcp.Solver.MemoryUsage(), 'bytes')\n",
|
||||
"# [END advanced]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
102
examples/notebook/constraint_solver/simple_routing_program.ipynb
Normal file
102
examples/notebook/constraint_solver/simple_routing_program.ipynb
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicle Routing example.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Entry point of the program.\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"# [START data]\n",
|
||||
"num_locations = 5\n",
|
||||
"num_vehicles = 1\n",
|
||||
"depot = 0\n",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# Create the routing index manager.\n",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot)\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START transit_callback]\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the absolute difference between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to user NodeIndex.\n",
|
||||
" from_node = int(manager.IndexToNode(from_index))\n",
|
||||
" to_node = int(manager.IndexToNode(to_index))\n",
|
||||
" return abs(to_node - from_node)\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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) # pylint: disable=no-member\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
"index = routing.Start(0)\n",
|
||||
"plan_output = 'Route for vehicle 0:\\n'\n",
|
||||
"route_distance = 0\n",
|
||||
"while not routing.IsEnd(index):\n",
|
||||
" plan_output += '{} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
"plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
"plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
"print(plan_output)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
155
examples/notebook/constraint_solver/tsp.ipynb
Normal file
155
examples/notebook/constraint_solver/tsp.ipynb
Normal file
@@ -0,0 +1,155 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Travelling Salesman Problem.\n",
|
||||
"\n",
|
||||
"A description of the problem can be found here:\n",
|
||||
"http://en.wikipedia.org/wiki/Travelling_salesman_problem.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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",
|
||||
" # Locations in block units\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",
|
||||
" (5, 5), (8, 5),\n",
|
||||
" (1, 6), (2, 6),\n",
|
||||
" (3, 7), (6, 7),\n",
|
||||
" (0, 8), (7, 8),]\n",
|
||||
" # Convert locations in meters using a city block dimension of 114m x 80m.\n",
|
||||
" data['locations'] = [(l[0] * 114, l[1] * 80) for l in locations]\n",
|
||||
" data['num_vehicles'] = 1\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START distance_callback]\n",
|
||||
"def create_distance_callback(data, manager):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" distances_ = {}\n",
|
||||
" index_manager_ = manager\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_counter, from_node in enumerate(data['locations']):\n",
|
||||
" distances_[from_counter] = {}\n",
|
||||
" for to_counter, to_node in enumerate(data['locations']):\n",
|
||||
" if from_counter == to_counter:\n",
|
||||
" distances_[from_counter][to_counter] = 0\n",
|
||||
" else:\n",
|
||||
" distances_[from_counter][to_counter] = (\n",
|
||||
" abs(from_node[0] - to_node[0]) +\n",
|
||||
" abs(from_node[1] - to_node[1]))\n",
|
||||
"\n",
|
||||
" def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the manhattan distance between the two nodes.\"\"\"\n",
|
||||
" # Convert from routing variable Index to distance matrix NodeIndex.\n",
|
||||
" from_node = index_manager_.IndexToNode(from_index)\n",
|
||||
" to_node = index_manager_.IndexToNode(to_index)\n",
|
||||
" return distances_[from_node][to_node]\n",
|
||||
"\n",
|
||||
" return distance_callback\n",
|
||||
" # [END distance_callback]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" index = routing.Start(0)\n",
|
||||
" plan_output = 'Route for vehicle 0:\\n'\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['locations']),\n",
|
||||
" 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",
|
||||
"distance_callback = create_distance_callback(data, manager)\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
187
examples/notebook/constraint_solver/tsp_circuit_board.ipynb
Normal file
187
examples/notebook/constraint_solver/tsp_circuit_board.ipynb
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple travelling salesman problem on a circuit board.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import math\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",
|
||||
" # Locations in block units\n",
|
||||
" data['locations'] = [\n",
|
||||
" (288, 149), (288, 129), (270, 133), (256, 141), (256, 157), (246, 157),\n",
|
||||
" (236, 169), (228, 169), (228, 161), (220, 169), (212, 169), (204, 169),\n",
|
||||
" (196, 169), (188, 169), (196, 161), (188, 145), (172, 145), (164, 145),\n",
|
||||
" (156, 145), (148, 145), (140, 145), (148, 169), (164, 169), (172, 169),\n",
|
||||
" (156, 169), (140, 169), (132, 169), (124, 169), (116, 161), (104, 153),\n",
|
||||
" (104, 161), (104, 169), (90, 165), (80, 157), (64, 157), (64, 165),\n",
|
||||
" (56, 169), (56, 161), (56, 153), (56, 145), (56, 137), (56, 129),\n",
|
||||
" (56, 121), (40, 121), (40, 129), (40, 137), (40, 145), (40, 153),\n",
|
||||
" (40, 161), (40, 169), (32, 169), (32, 161), (32, 153), (32, 145),\n",
|
||||
" (32, 137), (32, 129), (32, 121), (32, 113), (40, 113), (56, 113),\n",
|
||||
" (56, 105), (48, 99), (40, 99), (32, 97), (32, 89), (24, 89),\n",
|
||||
" (16, 97), (16, 109), (8, 109), (8, 97), (8, 89), (8, 81),\n",
|
||||
" (8, 73), (8, 65), (8, 57), (16, 57), (8, 49), (8, 41),\n",
|
||||
" (24, 45), (32, 41), (32, 49), (32, 57), (32, 65), (32, 73),\n",
|
||||
" (32, 81), (40, 83), (40, 73), (40, 63), (40, 51), (44, 43),\n",
|
||||
" (44, 35), (44, 27), (32, 25), (24, 25), (16, 25), (16, 17),\n",
|
||||
" (24, 17), (32, 17), (44, 11), (56, 9), (56, 17), (56, 25),\n",
|
||||
" (56, 33), (56, 41), (64, 41), (72, 41), (72, 49), (56, 49),\n",
|
||||
" (48, 51), (56, 57), (56, 65), (48, 63), (48, 73), (56, 73),\n",
|
||||
" (56, 81), (48, 83), (56, 89), (56, 97), (104, 97), (104, 105),\n",
|
||||
" (104, 113), (104, 121), (104, 129), (104, 137), (104, 145), (116, 145),\n",
|
||||
" (124, 145), (132, 145), (132, 137), (140, 137), (148, 137), (156, 137),\n",
|
||||
" (164, 137), (172, 125), (172, 117), (172, 109), (172, 101), (172, 93),\n",
|
||||
" (172, 85), (180, 85), (180, 77), (180, 69), (180, 61), (180, 53),\n",
|
||||
" (172, 53), (172, 61), (172, 69), (172, 77), (164, 81), (148, 85),\n",
|
||||
" (124, 85), (124, 93), (124, 109), (124, 125), (124, 117), (124, 101),\n",
|
||||
" (104, 89), (104, 81), (104, 73), (104, 65), (104, 49), (104, 41),\n",
|
||||
" (104, 33), (104, 25), (104, 17), (92, 9), (80, 9), (72, 9),\n",
|
||||
" (64, 21), (72, 25), (80, 25), (80, 25), (80, 41), (88, 49),\n",
|
||||
" (104, 57), (124, 69), (124, 77), (132, 81), (140, 65), (132, 61),\n",
|
||||
" (124, 61), (124, 53), (124, 45), (124, 37), (124, 29), (132, 21),\n",
|
||||
" (124, 21), (120, 9), (128, 9), (136, 9), (148, 9), (162, 9),\n",
|
||||
" (156, 25), (172, 21), (180, 21), (180, 29), (172, 29), (172, 37),\n",
|
||||
" (172, 45), (180, 45), (180, 37), (188, 41), (196, 49), (204, 57),\n",
|
||||
" (212, 65), (220, 73), (228, 69), (228, 77), (236, 77), (236, 69),\n",
|
||||
" (236, 61), (228, 61), (228, 53), (236, 53), (236, 45), (228, 45),\n",
|
||||
" (228, 37), (236, 37), (236, 29), (228, 29), (228, 21), (236, 21),\n",
|
||||
" (252, 21), (260, 29), (260, 37), (260, 45), (260, 53), (260, 61),\n",
|
||||
" (260, 69), (260, 77), (276, 77), (276, 69), (276, 61), (276, 53),\n",
|
||||
" (284, 53), (284, 61), (284, 69), (284, 77), (284, 85), (284, 93),\n",
|
||||
" (284, 101), (288, 109), (280, 109), (276, 101), (276, 93), (276, 85),\n",
|
||||
" (268, 97), (260, 109), (252, 101), (260, 93), (260, 85), (236, 85),\n",
|
||||
" (228, 85), (228, 93), (236, 93), (236, 101), (228, 101), (228, 109),\n",
|
||||
" (228, 117), (228, 125), (220, 125), (212, 117), (204, 109), (196, 101),\n",
|
||||
" (188, 93), (180, 93), (180, 101), (180, 109), (180, 117), (180, 125),\n",
|
||||
" (196, 145), (204, 145), (212, 145), (220, 145), (228, 145), (236, 145),\n",
|
||||
" (246, 141), (252, 125), (260, 129), (280, 133)\n",
|
||||
" ] # yapf: disable\n",
|
||||
" data['num_vehicles'] = 1\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START distance_callback]\n",
|
||||
"def compute_euclidean_distance_matrix(locations):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" distances = {}\n",
|
||||
" for from_counter, from_node in enumerate(locations):\n",
|
||||
" distances[from_counter] = {}\n",
|
||||
" for to_counter, to_node in enumerate(locations):\n",
|
||||
" if from_counter == to_counter:\n",
|
||||
" distances[from_counter][to_counter] = 0\n",
|
||||
" else:\n",
|
||||
" # Euclidean distance\n",
|
||||
" distances[from_counter][to_counter] = (int(\n",
|
||||
" math.hypot((from_node[0] - to_node[0]),\n",
|
||||
" (from_node[1] - to_node[1]))))\n",
|
||||
" return distances\n",
|
||||
" # [END distance_callback]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" index = routing.Start(0)\n",
|
||||
" plan_output = 'Route:\\n'\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" print(plan_output)\n",
|
||||
" plan_output += 'Objective: {}m\\n'.format(route_distance)\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['locations']),\n",
|
||||
" 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",
|
||||
"# [START transit_callback]\n",
|
||||
"distance_matrix = compute_euclidean_distance_matrix(data['locations'])\n",
|
||||
"\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 distance_matrix[from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
133
examples/notebook/constraint_solver/tsp_cities.ipynb
Normal file
133
examples/notebook/constraint_solver/tsp_cities.ipynb
Normal file
@@ -0,0 +1,133 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple travelling salesman problem between cities.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\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['distance_matrix'] = [\n",
|
||||
" [0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972],\n",
|
||||
" [2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579],\n",
|
||||
" [713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260],\n",
|
||||
" [1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987],\n",
|
||||
" [1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371],\n",
|
||||
" [1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999],\n",
|
||||
" [2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701],\n",
|
||||
" [213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099],\n",
|
||||
" [2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600],\n",
|
||||
" [875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162],\n",
|
||||
" [1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200],\n",
|
||||
" [2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504],\n",
|
||||
" [1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0],\n",
|
||||
" ] # yapf: disable\n",
|
||||
" data['num_vehicles'] = 1\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {} miles'.format(assignment.ObjectiveValue()))\n",
|
||||
" index = routing.Start(0)\n",
|
||||
" plan_output = 'Route for vehicle 0:\\n'\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" print(plan_output)\n",
|
||||
" plan_output += 'Route distance: {}miles\\n'.format(route_distance)\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
188
examples/notebook/constraint_solver/tsp_distance_matrix.ipynb
Normal file
188
examples/notebook/constraint_solver/tsp_distance_matrix.ipynb
Normal file
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Travelling Salesman Problem.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 1\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" index = routing.Start(0)\n",
|
||||
" plan_output = 'Route for vehicle 0:\\n'\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(previous_index, index, 0)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
193
examples/notebook/constraint_solver/vrp.ipynb
Normal file
193
examples/notebook/constraint_solver/vrp.ipynb
Normal file
@@ -0,0 +1,193 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Vehicles Routing Problem.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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",
|
||||
"# 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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
223
examples/notebook/constraint_solver/vrp_capacity.ipynb
Normal file
223
examples/notebook/constraint_solver/vrp_capacity.ipynb
Normal file
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Capacited Vehicles Routing Problem (CVRP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START demands_capacities]\n",
|
||||
" data['demands'] = [0, 1, 1, 2, 4, 2, 4, 8, 8, 1, 2, 1, 2, 4, 4, 8, 8]\n",
|
||||
" data['vehicle_capacities'] = [15, 15, 15, 15]\n",
|
||||
" # [END demands_capacities]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" route_load = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" route_load += data['demands'][node_index]\n",
|
||||
" plan_output += ' {0} Load({1}) -> '.format(node_index, route_load)\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += ' {0} Load({1})\\n'.format(manager.IndexToNode(index),\n",
|
||||
" route_load)\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" plan_output += 'Load of the route: {}\\n'.format(route_load)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" total_load += route_load\n",
|
||||
" print('Total distance of all routes: {}m'.format(total_distance))\n",
|
||||
" print('Total load of all routes: {}'.format(total_load))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\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['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"# [END transit_callback]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Capacity constraint.\n",
|
||||
"# [START capacity_constraint]\n",
|
||||
"def demand_callback(from_index):\n",
|
||||
" \"\"\"Returns the demand of the node.\"\"\"\n",
|
||||
" # Convert from routing variable Index to demands NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" return data['demands'][from_node]\n",
|
||||
"\n",
|
||||
"demand_callback_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" demand_callback)\n",
|
||||
"routing.AddDimensionWithVehicleCapacity(\n",
|
||||
" demand_callback_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacities'], # vehicle maximum capacities\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" 'Capacity')\n",
|
||||
"# [END capacity_constraint]\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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
236
examples/notebook/constraint_solver/vrp_drop_nodes.ipynb
Normal file
236
examples/notebook/constraint_solver/vrp_drop_nodes.ipynb
Normal file
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Capacited Vehicles Routing Problem (CVRP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START demands_capacities]\n",
|
||||
" data['demands'] = [0, 1, 1, 3, 6, 3, 6, 8, 8, 1, 2, 1, 2, 6, 6, 8, 8]\n",
|
||||
" data['vehicle_capacities'] = [15, 15, 15, 15]\n",
|
||||
" # [END demands_capacities]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" # Display dropped nodes.\n",
|
||||
" dropped_nodes = 'Dropped nodes:'\n",
|
||||
" for node in range(routing.Size()):\n",
|
||||
" if routing.IsStart(node) or routing.IsEnd(node):\n",
|
||||
" continue\n",
|
||||
" if assignment.Value(routing.NextVar(node)) == node:\n",
|
||||
" dropped_nodes += ' {}'.format(manager.IndexToNode(node))\n",
|
||||
" print(dropped_nodes)\n",
|
||||
" # Display routes\n",
|
||||
" total_distance = 0\n",
|
||||
" total_load = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" route_load = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" node_index = manager.IndexToNode(index)\n",
|
||||
" route_load += data['demands'][node_index]\n",
|
||||
" plan_output += ' {0} Load({1}) -> '.format(node_index, route_load)\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += ' {0} Load({1})\\n'.format(manager.IndexToNode(index),\n",
|
||||
" route_load)\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" plan_output += 'Load of the route: {}\\n'.format(route_load)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" total_load += route_load\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" print('Total Load of all routes: {}'.format(total_load))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\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['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"# [END transit_callback]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Capacity constraint.\n",
|
||||
"# [START capacity_constraint]\n",
|
||||
"def demand_callback(from_index):\n",
|
||||
" \"\"\"Returns the demand of the node.\"\"\"\n",
|
||||
" # Convert from routing variable Index to demands NodeIndex.\n",
|
||||
" from_node = manager.IndexToNode(from_index)\n",
|
||||
" return data['demands'][from_node]\n",
|
||||
"\n",
|
||||
"demand_callback_index = routing.RegisterUnaryTransitCallback(\n",
|
||||
" demand_callback)\n",
|
||||
"routing.AddDimensionWithVehicleCapacity(\n",
|
||||
" demand_callback_index,\n",
|
||||
" 0, # null capacity slack\n",
|
||||
" data['vehicle_capacities'], # vehicle maximum capacities\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" 'Capacity')\n",
|
||||
"# Allow to drop nodes.\n",
|
||||
"penalty = 1000\n",
|
||||
"for node in range(1, len(data['distance_matrix'])):\n",
|
||||
" routing.AddDisjunction([manager.NodeToIndex(node)], penalty)\n",
|
||||
"# [END capacity_constraint]\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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
207
examples/notebook/constraint_solver/vrp_global_span.ipynb
Normal file
207
examples/notebook/constraint_solver/vrp_global_span.ipynb
Normal file
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicles Routing Problem (VRP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\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['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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 Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\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",
|
||||
"# [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(data, manager, routing, solution)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
223
examples/notebook/constraint_solver/vrp_initial_routes.ipynb
Normal file
223
examples/notebook/constraint_solver/vrp_initial_routes.ipynb
Normal file
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicles Routing Problem (VRP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START initial_routes]\n",
|
||||
" data['initial_routes'] = [\n",
|
||||
" [8, 16, 14, 13, 12, 11],\n",
|
||||
" [3, 4, 9, 10],\n",
|
||||
" [15, 1],\n",
|
||||
" [7, 5, 2, 6],\n",
|
||||
" ]\n",
|
||||
" # [END initial_routes]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" 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",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [END solution_printer]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Solve the CVRP problem.\"\"\"\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['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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 Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\n",
|
||||
"\n",
|
||||
"# [START print_initial_solution]\n",
|
||||
"initial_solution = routing.ReadAssignmentFromRoutes(data['initial_routes'],\n",
|
||||
" True)\n",
|
||||
"print('Initial solution:')\n",
|
||||
"print_solution(data, manager, routing, initial_solution)\n",
|
||||
"# [END print_initial_solution]\n",
|
||||
"\n",
|
||||
"# Set default search parameters.\n",
|
||||
"# [START parameters]\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"solution = routing.SolveFromAssignmentWithParameters(\n",
|
||||
" initial_solution, search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if solution:\n",
|
||||
" print('Solution after search:')\n",
|
||||
" print_solution(data, manager, routing, solution)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
227
examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb
Normal file
227
examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START pickups_deliveries]\n",
|
||||
" data['pickups_deliveries'] = [\n",
|
||||
" [1, 6],\n",
|
||||
" [2, 10],\n",
|
||||
" [4, 3],\n",
|
||||
" [5, 9],\n",
|
||||
" [7, 8],\n",
|
||||
" [15, 11],\n",
|
||||
" [13, 12],\n",
|
||||
" [16, 14],\n",
|
||||
" ]\n",
|
||||
" # [END pickups_deliveries]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the manhattan 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\n",
|
||||
"\n",
|
||||
"# Define Transportation Requests.\n",
|
||||
"# [START pickup_delivery_constraint]\n",
|
||||
"for request in data['pickups_deliveries']:\n",
|
||||
" pickup_index = manager.NodeToIndex(request[0])\n",
|
||||
" delivery_index = manager.NodeToIndex(request[1])\n",
|
||||
" routing.AddPickupAndDelivery(pickup_index, delivery_index)\n",
|
||||
" routing.solver().Add(\n",
|
||||
" routing.VehicleVar(pickup_index) == routing.VehicleVar(\n",
|
||||
" delivery_index))\n",
|
||||
" routing.solver().Add(\n",
|
||||
" distance_dimension.CumulVar(pickup_index) <=\n",
|
||||
" distance_dimension.CumulVar(delivery_index))\n",
|
||||
"# [END pickup_delivery_constraint]\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.PARALLEL_CHEAPEST_INSERTION)\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START pickups_deliveries]\n",
|
||||
" data['pickups_deliveries'] = [\n",
|
||||
" [1, 6],\n",
|
||||
" [2, 10],\n",
|
||||
" [4, 3],\n",
|
||||
" [5, 9],\n",
|
||||
" [7, 8],\n",
|
||||
" [15, 11],\n",
|
||||
" [13, 12],\n",
|
||||
" [16, 14],\n",
|
||||
" ]\n",
|
||||
" # [END pickups_deliveries]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the manhattan 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\n",
|
||||
"\n",
|
||||
"# Define Transportation Requests.\n",
|
||||
"# [START pickup_delivery_constraint]\n",
|
||||
"for request in data['pickups_deliveries']:\n",
|
||||
" pickup_index = manager.NodeToIndex(request[0])\n",
|
||||
" delivery_index = manager.NodeToIndex(request[1])\n",
|
||||
" routing.AddPickupAndDelivery(pickup_index, delivery_index)\n",
|
||||
" routing.solver().Add(\n",
|
||||
" routing.VehicleVar(pickup_index) == routing.VehicleVar(\n",
|
||||
" delivery_index))\n",
|
||||
" routing.solver().Add(\n",
|
||||
" distance_dimension.CumulVar(pickup_index) <=\n",
|
||||
" distance_dimension.CumulVar(delivery_index))\n",
|
||||
"routing.SetPickupAndDeliveryPolicyOfAllVehicles(\n",
|
||||
" pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_FIFO)\n",
|
||||
"# [END pickup_delivery_constraint]\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.PARALLEL_CHEAPEST_INSERTION)\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" # [START pickups_deliveries]\n",
|
||||
" data['pickups_deliveries'] = [\n",
|
||||
" [1, 6],\n",
|
||||
" [2, 10],\n",
|
||||
" [4, 3],\n",
|
||||
" [5, 9],\n",
|
||||
" [7, 8],\n",
|
||||
" [15, 11],\n",
|
||||
" [13, 12],\n",
|
||||
" [16, 14],\n",
|
||||
" ]\n",
|
||||
" # [END pickups_deliveries]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += route_distance\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
" # [END solution_printer]\n",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Define cost of each arc.\n",
|
||||
"# [START arc_cost]\n",
|
||||
"def distance_callback(from_index, to_index):\n",
|
||||
" \"\"\"Returns the manhattan 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n",
|
||||
"# [END arc_cost]\n",
|
||||
"\n",
|
||||
"# Add Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\n",
|
||||
"\n",
|
||||
"# Define Transportation Requests.\n",
|
||||
"# [START pickup_delivery_constraint]\n",
|
||||
"for request in data['pickups_deliveries']:\n",
|
||||
" pickup_index = manager.NodeToIndex(request[0])\n",
|
||||
" delivery_index = manager.NodeToIndex(request[1])\n",
|
||||
" routing.AddPickupAndDelivery(pickup_index, delivery_index)\n",
|
||||
" routing.solver().Add(\n",
|
||||
" routing.VehicleVar(pickup_index) == routing.VehicleVar(\n",
|
||||
" delivery_index))\n",
|
||||
" routing.solver().Add(\n",
|
||||
" distance_dimension.CumulVar(pickup_index) <=\n",
|
||||
" distance_dimension.CumulVar(delivery_index))\n",
|
||||
"routing.SetPickupAndDeliveryPolicyOfAllVehicles(\n",
|
||||
" pywrapcp.RoutingModel.PICKUP_AND_DELIVERY_LIFO)\n",
|
||||
"# [END pickup_delivery_constraint]\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.PARALLEL_CHEAPEST_INSERTION)\n",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
227
examples/notebook/constraint_solver/vrp_resources.ipynb
Normal file
227
examples/notebook/constraint_solver/vrp_resources.ipynb
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicles Routing Problem (VRP) with Resource Constraints.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['time_matrix'] = [\n",
|
||||
" [0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7],\n",
|
||||
" [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14],\n",
|
||||
" [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9],\n",
|
||||
" [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16],\n",
|
||||
" [7, 2, 10, 1, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14],\n",
|
||||
" [3, 6, 6, 7, 6, 0, 2, 3, 2, 2, 7, 9, 7, 7, 6, 12, 8],\n",
|
||||
" [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5],\n",
|
||||
" [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 8, 5, 4, 3, 7, 8, 10],\n",
|
||||
" [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6],\n",
|
||||
" [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5],\n",
|
||||
" [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4],\n",
|
||||
" [6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 3, 10],\n",
|
||||
" [4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 6, 4, 8],\n",
|
||||
" [4, 8, 13, 9, 8, 7, 10, 3, 7, 4, 8, 3, 2, 0, 4, 5, 6],\n",
|
||||
" [5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 6, 4, 0, 9, 2],\n",
|
||||
" [9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9],\n",
|
||||
" [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0],\n",
|
||||
" ]\n",
|
||||
" data['time_windows'] = [\n",
|
||||
" (0, 5), # depot\n",
|
||||
" (7, 12), # 1\n",
|
||||
" (10, 15), # 2\n",
|
||||
" (5, 14), # 3\n",
|
||||
" (5, 13), # 4\n",
|
||||
" (0, 5), # 5\n",
|
||||
" (5, 10), # 6\n",
|
||||
" (0, 10), # 7\n",
|
||||
" (5, 10), # 8\n",
|
||||
" (0, 5), # 9\n",
|
||||
" (10, 16), # 10\n",
|
||||
" (10, 15), # 11\n",
|
||||
" (0, 5), # 12\n",
|
||||
" (5, 10), # 13\n",
|
||||
" (7, 12), # 14\n",
|
||||
" (10, 15), # 15\n",
|
||||
" (5, 15), # 16\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" # [START resources_data]\n",
|
||||
" data['vehicle_load_time'] = 5\n",
|
||||
" data['vehicle_unload_time'] = 5\n",
|
||||
" data['depot_capacity'] = 2\n",
|
||||
" # [END resources_data]\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += '{0} Time({1},{2}) -> '.format(\n",
|
||||
" manager.IndexToNode(index), assignment.Min(time_var),\n",
|
||||
" assignment.Max(time_var))\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += '{0} Time({1},{2})\\n'.format(manager.IndexToNode(index),\n",
|
||||
" assignment.Min(time_var),\n",
|
||||
" assignment.Max(time_var))\n",
|
||||
" plan_output += 'Time of the route: {}min\\n'.format(\n",
|
||||
" assignment.Min(time_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_time += assignment.Min(time_var)\n",
|
||||
" print('Total time of all routes: {}min'.format(total_time))\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']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\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 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]\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",
|
||||
"# [START time_windows_constraint]\n",
|
||||
"time = 'Time'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 60, # allow waiting time\n",
|
||||
" 60, # maximum time per vehicle\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",
|
||||
"for location_idx, time_window in enumerate(data['time_windows']):\n",
|
||||
" if location_idx == 0:\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",
|
||||
"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",
|
||||
"# [END time_windows_constraint]\n",
|
||||
"\n",
|
||||
"# Add resource constraints at the depot.\n",
|
||||
"# [START depot_load_time]\n",
|
||||
"solver = routing.solver()\n",
|
||||
"intervals = []\n",
|
||||
"for i in range(data['num_vehicles']):\n",
|
||||
" # Add time windows at start of routes\n",
|
||||
" intervals.append(\n",
|
||||
" solver.FixedDurationIntervalVar(\n",
|
||||
" time_dimension.CumulVar(routing.Start(i)),\n",
|
||||
" data['vehicle_load_time'], 'depot_interval'))\n",
|
||||
" # Add time windows at end of routes.\n",
|
||||
" intervals.append(\n",
|
||||
" solver.FixedDurationIntervalVar(\n",
|
||||
" time_dimension.CumulVar(routing.End(i)),\n",
|
||||
" data['vehicle_unload_time'], 'depot_interval'))\n",
|
||||
"# [END depot_load_time]\n",
|
||||
"\n",
|
||||
"# [START depot_capacity]\n",
|
||||
"depot_usage = [1 for i in range(len(intervals))]\n",
|
||||
"solver.Add(\n",
|
||||
" solver.Cumulative(intervals, depot_usage, data['depot_capacity'],\n",
|
||||
" 'depot'))\n",
|
||||
"# [END depot_capacity]\n",
|
||||
"\n",
|
||||
"# Instantiate route start and end times to produce feasible times.\n",
|
||||
"# [START depot_start_end_times]\n",
|
||||
"for i in range(data['num_vehicles']):\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.Start(i)))\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.End(i)))\n",
|
||||
"# [END depot_start_end_times]\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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"else:\n",
|
||||
" print('No solution found !')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
209
examples/notebook/constraint_solver/vrp_starts_ends.ipynb
Normal file
209
examples/notebook/constraint_solver/vrp_starts_ends.ipynb
Normal file
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Simple Vehicles Routing Problem.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['distance_matrix'] = [\n",
|
||||
" [\n",
|
||||
" 0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354,\n",
|
||||
" 468, 776, 662\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674,\n",
|
||||
" 1016, 868, 1210\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164,\n",
|
||||
" 1130, 788, 1552, 754\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822,\n",
|
||||
" 1164, 560, 1358\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708,\n",
|
||||
" 1050, 674, 1244\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628,\n",
|
||||
" 514, 1050, 708\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856,\n",
|
||||
" 514, 1278, 480\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320,\n",
|
||||
" 662, 742, 856\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662,\n",
|
||||
" 320, 1084, 514\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388,\n",
|
||||
" 274, 810, 468\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764,\n",
|
||||
" 730, 388, 1152, 354\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114,\n",
|
||||
" 308, 650, 274, 844\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194,\n",
|
||||
" 536, 388, 730\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0,\n",
|
||||
" 342, 422, 536\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536,\n",
|
||||
" 342, 0, 764, 194\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274,\n",
|
||||
" 388, 422, 764, 0, 798\n",
|
||||
" ],\n",
|
||||
" [\n",
|
||||
" 662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730,\n",
|
||||
" 536, 194, 798, 0\n",
|
||||
" ],\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" # [START starts_ends]\n",
|
||||
" data['starts'] = [1, 2, 15, 16]\n",
|
||||
" data['ends'] = [0, 0, 0, 0]\n",
|
||||
" # [END starts_ends]\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" 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",
|
||||
"\n",
|
||||
"\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",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n",
|
||||
" data['num_vehicles'], data['starts'],\n",
|
||||
" data['ends'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 data['distance_matrix'][from_node][to_node]\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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 Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 2000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\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",
|
||||
"# [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(data, manager, routing, solution)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
196
examples/notebook/constraint_solver/vrp_time_windows.ipynb
Normal file
196
examples/notebook/constraint_solver/vrp_time_windows.ipynb
Normal file
@@ -0,0 +1,196 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicles Routing Problem (VRP) with Time Windows.\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\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['time_matrix'] = [\n",
|
||||
" [0, 6, 9, 8, 7, 3, 6, 2, 3, 2, 6, 6, 4, 4, 5, 9, 7],\n",
|
||||
" [6, 0, 8, 3, 2, 6, 8, 4, 8, 8, 13, 7, 5, 8, 12, 10, 14],\n",
|
||||
" [9, 8, 0, 11, 10, 6, 3, 9, 5, 8, 4, 15, 14, 13, 9, 18, 9],\n",
|
||||
" [8, 3, 11, 0, 1, 7, 10, 6, 10, 10, 14, 6, 7, 9, 14, 6, 16],\n",
|
||||
" [7, 2, 10, 1, 0, 6, 9, 4, 8, 9, 13, 4, 6, 8, 12, 8, 14],\n",
|
||||
" [3, 6, 6, 7, 6, 0, 2, 3, 2, 2, 7, 9, 7, 7, 6, 12, 8],\n",
|
||||
" [6, 8, 3, 10, 9, 2, 0, 6, 2, 5, 4, 12, 10, 10, 6, 15, 5],\n",
|
||||
" [2, 4, 9, 6, 4, 3, 6, 0, 4, 4, 8, 5, 4, 3, 7, 8, 10],\n",
|
||||
" [3, 8, 5, 10, 8, 2, 2, 4, 0, 3, 4, 9, 8, 7, 3, 13, 6],\n",
|
||||
" [2, 8, 8, 10, 9, 2, 5, 4, 3, 0, 4, 6, 5, 4, 3, 9, 5],\n",
|
||||
" [6, 13, 4, 14, 13, 7, 4, 8, 4, 4, 0, 10, 9, 8, 4, 13, 4],\n",
|
||||
" [6, 7, 15, 6, 4, 9, 12, 5, 9, 6, 10, 0, 1, 3, 7, 3, 10],\n",
|
||||
" [4, 5, 14, 7, 6, 7, 10, 4, 8, 5, 9, 1, 0, 2, 6, 4, 8],\n",
|
||||
" [4, 8, 13, 9, 8, 7, 10, 3, 7, 4, 8, 3, 2, 0, 4, 5, 6],\n",
|
||||
" [5, 12, 9, 14, 12, 6, 6, 7, 3, 3, 4, 7, 6, 4, 0, 9, 2],\n",
|
||||
" [9, 10, 18, 6, 8, 12, 15, 8, 13, 9, 13, 3, 4, 5, 9, 0, 9],\n",
|
||||
" [7, 14, 9, 16, 14, 8, 5, 10, 6, 5, 4, 10, 8, 6, 2, 9, 0],\n",
|
||||
" ]\n",
|
||||
" data['time_windows'] = [\n",
|
||||
" (0, 5), # depot\n",
|
||||
" (7, 12), # 1\n",
|
||||
" (10, 15), # 2\n",
|
||||
" (5, 14), # 3\n",
|
||||
" (5, 13), # 4\n",
|
||||
" (0, 5), # 5\n",
|
||||
" (5, 10), # 6\n",
|
||||
" (0, 10), # 7\n",
|
||||
" (5, 10), # 8\n",
|
||||
" (0, 5), # 9\n",
|
||||
" (10, 16), # 10\n",
|
||||
" (10, 15), # 11\n",
|
||||
" (0, 5), # 12\n",
|
||||
" (5, 10), # 13\n",
|
||||
" (7, 12), # 14\n",
|
||||
" (10, 15), # 15\n",
|
||||
" (5, 15), # 16\n",
|
||||
" ]\n",
|
||||
" data['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\n",
|
||||
" # [END data_model]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(data, manager, routing, assignment):\n",
|
||||
" \"\"\"Prints assignment on console.\"\"\"\n",
|
||||
" time_dimension = routing.GetDimensionOrDie('Time')\n",
|
||||
" total_time = 0\n",
|
||||
" for vehicle_id in range(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += '{0} Time({1},{2}) -> '.format(\n",
|
||||
" manager.IndexToNode(index), assignment.Min(time_var),\n",
|
||||
" assignment.Max(time_var))\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" time_var = time_dimension.CumulVar(index)\n",
|
||||
" plan_output += '{0} Time({1},{2})\\n'.format(manager.IndexToNode(index),\n",
|
||||
" assignment.Min(time_var),\n",
|
||||
" assignment.Max(time_var))\n",
|
||||
" plan_output += 'Time of the route: {}min\\n'.format(\n",
|
||||
" assignment.Min(time_var))\n",
|
||||
" print(plan_output)\n",
|
||||
" total_time += assignment.Min(time_var)\n",
|
||||
" print('Total time of all routes: {}min'.format(total_time))\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']),\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\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 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]\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",
|
||||
"# [START time_windows_constraint]\n",
|
||||
"time = 'Time'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 30, # allow waiting time\n",
|
||||
" 30, # maximum time per vehicle\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",
|
||||
"for location_idx, time_window in enumerate(data['time_windows']):\n",
|
||||
" if location_idx == 0:\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",
|
||||
"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",
|
||||
"# [END time_windows_constraint]\n",
|
||||
"\n",
|
||||
"# Instantiate route start and end times to produce feasible times.\n",
|
||||
"# [START depot_start_end_times]\n",
|
||||
"for i in range(data['num_vehicles']):\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.Start(i)))\n",
|
||||
" routing.AddVariableMinimizedByFinalizer(\n",
|
||||
" time_dimension.CumulVar(routing.End(i)))\n",
|
||||
"# [END depot_start_end_times]\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",
|
||||
"# [END parameters]\n",
|
||||
"\n",
|
||||
"# Solve the problem.\n",
|
||||
"# [START solve]\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"# [END solve]\n",
|
||||
"\n",
|
||||
"# Print solution on console.\n",
|
||||
"# [START print_solution]\n",
|
||||
"if assignment:\n",
|
||||
" print_solution(data, manager, routing, assignment)\n",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
130
examples/notebook/constraint_solver/vrp_with_time_limit.ipynb
Normal file
130
examples/notebook/constraint_solver/vrp_with_time_limit.ipynb
Normal file
@@ -0,0 +1,130 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"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",
|
||||
"# [START program]\n",
|
||||
"\"\"\"Vehicles Routing Problem (VRP).\"\"\"\n",
|
||||
"\n",
|
||||
"# [START import]\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"# [END import]\n",
|
||||
"\n",
|
||||
"# [START solution_printer]\n",
|
||||
"def print_solution(manager, routing, solution):\n",
|
||||
" \"\"\"Prints solution on console.\"\"\"\n",
|
||||
" max_route_distance = 0\n",
|
||||
" for vehicle_id in range(manager.GetNumberOfVehicles()):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" route_distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} -> '.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = solution.Value(routing.NextVar(index))\n",
|
||||
" route_distance += routing.GetArcCostForVehicle(\n",
|
||||
" previous_index, index, vehicle_id)\n",
|
||||
" plan_output += '{}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(route_distance)\n",
|
||||
" 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",
|
||||
"\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",
|
||||
"# [END data]\n",
|
||||
"\n",
|
||||
"# Create the routing index manager.\n",
|
||||
"# [START index_manager]\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(\n",
|
||||
" num_locations, num_vehicles, depot)\n",
|
||||
"# [END index_manager]\n",
|
||||
"\n",
|
||||
"# Create Routing Model.\n",
|
||||
"# [START routing_model]\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# [END routing_model]\n",
|
||||
"\n",
|
||||
"# Create and register a transit callback.\n",
|
||||
"# [START 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 1\n",
|
||||
"\n",
|
||||
"transit_callback_index = routing.RegisterTransitCallback(distance_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 Distance constraint.\n",
|
||||
"# [START distance_constraint]\n",
|
||||
"dimension_name = 'Distance'\n",
|
||||
"routing.AddDimension(\n",
|
||||
" transit_callback_index,\n",
|
||||
" 0, # no slack\n",
|
||||
" 3000, # vehicle maximum travel distance\n",
|
||||
" True, # start cumul to zero\n",
|
||||
" dimension_name)\n",
|
||||
"distance_dimension = routing.GetDimensionOrDie(dimension_name)\n",
|
||||
"distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"# [END distance_constraint]\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(10)\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",
|
||||
"# [END print_solution]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
174
examples/notebook/constraint_solver/vrpgs.ipynb
Normal file
174
examples/notebook/constraint_solver/vrpgs.ipynb
Normal file
@@ -0,0 +1,174 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"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",
|
||||
"# 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",
|
||||
"\"\"\"Vehicle Routing Problem (VRP).\n",
|
||||
"\n",
|
||||
" This is a sample using the routing library python wrapper to solve a VRP\n",
|
||||
" problem.\n",
|
||||
" A description of the problem can be found here:\n",
|
||||
" http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n",
|
||||
"\n",
|
||||
" Distances are in meters.\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from functools import partial\n",
|
||||
"from six.moves import xrange\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from ortools.constraint_solver import routing_enums_pb2\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########################\n",
|
||||
"# Problem Data Definition #\n",
|
||||
"###########################\n",
|
||||
"def create_data_model():\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",
|
||||
" (0, 1), (1, 1),\n",
|
||||
" (5, 2), (7, 2),\n",
|
||||
" (3, 3), (6, 3),\n",
|
||||
" (5, 5), (8, 5),\n",
|
||||
" (1, 6), (2, 6),\n",
|
||||
" (3, 7), (6, 7),\n",
|
||||
" (0, 8), (7, 8)]\n",
|
||||
" # Compute locations in meters using the block dimension defined as follow\n",
|
||||
" # 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['num_vehicles'] = 4\n",
|
||||
" data['depot'] = 0\n",
|
||||
" return data\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",
|
||||
"\n",
|
||||
"\n",
|
||||
"def create_distance_evaluator(data):\n",
|
||||
" \"\"\"Creates callback to return distance between points.\"\"\"\n",
|
||||
" _distances = {}\n",
|
||||
" # precompute distance between location to have distance callback in O(1)\n",
|
||||
" for from_node in xrange(data['num_locations']):\n",
|
||||
" _distances[from_node] = {}\n",
|
||||
" for to_node in xrange(data['num_locations']):\n",
|
||||
" if from_node == to_node:\n",
|
||||
" _distances[from_node][to_node] = 0\n",
|
||||
" else:\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",
|
||||
" to_node)]\n",
|
||||
"\n",
|
||||
" return distance_evaluator\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def add_distance_dimension(routing, distance_evaluator_index):\n",
|
||||
" \"\"\"Add Global Span constraint\"\"\"\n",
|
||||
" distance = 'Distance'\n",
|
||||
" routing.AddDimension(\n",
|
||||
" distance_evaluator_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",
|
||||
" # Try to minimize the max distance among vehicles.\n",
|
||||
" # /!\\ It doesn't mean the standard deviation is minimized\n",
|
||||
" distance_dimension.SetGlobalSpanCostCoefficient(100)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"###########\n",
|
||||
"# Printer #\n",
|
||||
"###########\n",
|
||||
"def print_solution(data, routing, manager, assignment): # pylint:disable=too-many-locals\n",
|
||||
" \"\"\"Prints assignment on console\"\"\"\n",
|
||||
" print('Objective: {}'.format(assignment.ObjectiveValue()))\n",
|
||||
" total_distance = 0\n",
|
||||
" for vehicle_id in xrange(data['num_vehicles']):\n",
|
||||
" index = routing.Start(vehicle_id)\n",
|
||||
" plan_output = 'Route for vehicle {}:\\n'.format(vehicle_id)\n",
|
||||
" distance = 0\n",
|
||||
" while not routing.IsEnd(index):\n",
|
||||
" plan_output += ' {} ->'.format(manager.IndexToNode(index))\n",
|
||||
" previous_index = index\n",
|
||||
" index = assignment.Value(routing.NextVar(index))\n",
|
||||
" distance += routing.GetArcCostForVehicle(previous_index, index,\n",
|
||||
" vehicle_id)\n",
|
||||
" plan_output += ' {}\\n'.format(manager.IndexToNode(index))\n",
|
||||
" plan_output += 'Distance of the route: {}m\\n'.format(distance)\n",
|
||||
" print(plan_output)\n",
|
||||
" total_distance += distance\n",
|
||||
" print('Total Distance of all routes: {}m'.format(total_distance))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"########\n",
|
||||
"# Main #\n",
|
||||
"########\n",
|
||||
"\"\"\"Entry point of the program\"\"\"\n",
|
||||
"# Instantiate the data problem.\n",
|
||||
"data = create_data_model()\n",
|
||||
"\n",
|
||||
"# Create the routing index manager\n",
|
||||
"manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n",
|
||||
" data['num_vehicles'], data['depot'])\n",
|
||||
"\n",
|
||||
"# Create Routing Model\n",
|
||||
"routing = pywrapcp.RoutingModel(manager)\n",
|
||||
"\n",
|
||||
"# Define weight of each edge\n",
|
||||
"distance_evaluator_index = routing.RegisterTransitCallback(\n",
|
||||
" partial(create_distance_evaluator(data), manager))\n",
|
||||
"routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n",
|
||||
"add_distance_dimension(routing, distance_evaluator_index)\n",
|
||||
"\n",
|
||||
"# Setting first solution heuristic (cheapest addition).\n",
|
||||
"search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n",
|
||||
"search_parameters.first_solution_strategy = (\n",
|
||||
" routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n",
|
||||
"# Solve the problem.\n",
|
||||
"assignment = routing.SolveWithParameters(search_parameters)\n",
|
||||
"print_solution(data, routing, manager, assignment)\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
176
examples/notebook/contrib/3_jugs_mip.ipynb
Normal file
176
examples/notebook/contrib/3_jugs_mip.ipynb
Normal file
@@ -0,0 +1,176 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" 3 jugs problem using MIP in Google or-tools.\n",
|
||||
"\n",
|
||||
" A.k.a. water jugs problem.\n",
|
||||
"\n",
|
||||
" Problem from Taha 'Introduction to Operations Research',\n",
|
||||
" page 245f .\n",
|
||||
"\n",
|
||||
" Compare with the CP model:\n",
|
||||
" http://www.hakank.org/google_or_tools/3_jugs_regular\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCBC',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 15\n",
|
||||
"start = 0 # start node\n",
|
||||
"end = 14 # end node\n",
|
||||
"M = 999 # a large number\n",
|
||||
"\n",
|
||||
"nodes = [\n",
|
||||
" '8,0,0', # start\n",
|
||||
" '5,0,3',\n",
|
||||
" '5,3,0',\n",
|
||||
" '2,3,3',\n",
|
||||
" '2,5,1',\n",
|
||||
" '7,0,1',\n",
|
||||
" '7,1,0',\n",
|
||||
" '4,1,3',\n",
|
||||
" '3,5,0',\n",
|
||||
" '3,2,3',\n",
|
||||
" '6,2,0',\n",
|
||||
" '6,0,2',\n",
|
||||
" '1,5,2',\n",
|
||||
" '1,4,3',\n",
|
||||
" '4,4,0' # goal!\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# distance\n",
|
||||
"d = [[M, 1, M, M, M, M, M, M, 1, M, M, M, M, M, M],\n",
|
||||
" [M, M, 1, M, M, M, M, M, M, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, 1, M, M, M, M, 1, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, M, 1, M, M, M, M, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, M, M, 1, M, M, 1, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, M, M, M, 1, M, M, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, M, M, M, M, 1, 1, M, M, M, M, M, M],\n",
|
||||
" [M, M, M, M, M, M, M, M, M, M, M, M, M, M, 1],\n",
|
||||
" [M, M, M, M, M, M, M, M, M, 1, M, M, M, M, M],\n",
|
||||
" [M, 1, M, M, M, M, M, M, M, M, 1, M, M, M, M],\n",
|
||||
" [M, M, M, M, M, M, M, M, M, M, M, 1, M, M, M],\n",
|
||||
" [M, 1, M, M, M, M, M, M, M, M, M, M, 1, M, M],\n",
|
||||
" [M, M, M, M, M, M, M, M, M, M, M, M, M, 1, M],\n",
|
||||
" [M, 1, M, M, M, M, M, M, M, M, M, M, M, M, 1],\n",
|
||||
" [M, M, M, M, M, M, M, M, M, M, M, M, M, M, M]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# requirements (right hand statement)\n",
|
||||
"rhs = [solver.IntVar(-1, 1, 'rhs[%i]' % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(0, 1, 'x[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"out_flow = [solver.IntVar(0, 1, 'out_flow[%i]' % i) for i in range(n)]\n",
|
||||
"in_flow = [solver.IntVar(0, 1, 'in_flow[%i]' % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"# length of path, to be minimized\n",
|
||||
"z = solver.Sum(\n",
|
||||
" [d[i][j] * x[i, j] for i in range(n) for j in range(n) if d[i][j] < M])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" if i == start:\n",
|
||||
" solver.Add(rhs[i] == 1)\n",
|
||||
" elif i == end:\n",
|
||||
" solver.Add(rhs[i] == -1)\n",
|
||||
" else:\n",
|
||||
" solver.Add(rhs[i] == 0)\n",
|
||||
"\n",
|
||||
"# outflow constraint\n",
|
||||
"for i in range(n):\n",
|
||||
" solver.Add(\n",
|
||||
" out_flow[i] == solver.Sum([x[i, j] for j in range(n) if d[i][j] < M]))\n",
|
||||
"\n",
|
||||
"# inflow constraint\n",
|
||||
"for j in range(n):\n",
|
||||
" solver.Add(\n",
|
||||
" in_flow[j] == solver.Sum([x[i, j] for i in range(n) if d[i][j] < M]))\n",
|
||||
"\n",
|
||||
"# inflow = outflow\n",
|
||||
"for i in range(n):\n",
|
||||
" solver.Add(out_flow[i] - in_flow[i] == rhs[i])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(z)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('z: ', int(solver.Objective().Value()))\n",
|
||||
"\n",
|
||||
"t = start\n",
|
||||
"while t != end:\n",
|
||||
" print(nodes[t], '->', end=' ')\n",
|
||||
" for j in range(n):\n",
|
||||
" if x[t, j].SolutionValue() == 1:\n",
|
||||
" print(nodes[j])\n",
|
||||
" t = j\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
269
examples/notebook/contrib/3_jugs_regular.ipynb
Normal file
269
examples/notebook/contrib/3_jugs_regular.ipynb
Normal file
@@ -0,0 +1,269 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" 3 jugs problem using regular constraint in Google CP Solver.\n",
|
||||
"\n",
|
||||
" A.k.a. water jugs problem.\n",
|
||||
"\n",
|
||||
" Problem from Taha 'Introduction to Operations Research',\n",
|
||||
" page 245f .\n",
|
||||
"\n",
|
||||
" For more info about the problem, see:\n",
|
||||
" http://mathworld.wolfram.com/ThreeJugProblem.html\n",
|
||||
"\n",
|
||||
" This model use a regular constraint for handling the\n",
|
||||
" transitions between the states. Instead of minimizing\n",
|
||||
" the cost in a cost matrix (as shortest path problem),\n",
|
||||
" we here call the model with increasing length of the\n",
|
||||
" sequence array (x).\n",
|
||||
"\n",
|
||||
" Compare with other models that use MIP/CP approach,\n",
|
||||
" as a shortest path problem:\n",
|
||||
" * Comet: http://www.hakank.org/comet/3_jugs.co\n",
|
||||
" * Comet: http://www.hakank.org/comet/water_buckets1.co\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/3_jugs.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/3_jugs2.mzn\n",
|
||||
" * SICStus: http://www.hakank.org/sicstus/3_jugs.pl\n",
|
||||
" * ECLiPSe: http://www.hakank.org/eclipse/3_jugs.ecl\n",
|
||||
" * ECLiPSe: http://www.hakank.org/eclipse/3_jugs2.ecl\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/3_jugs2.cpp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from collections import defaultdict\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Global constraint regular\n",
|
||||
"#\n",
|
||||
"# This is a translation of MiniZinc's regular constraint (defined in\n",
|
||||
"# lib/zinc/globals.mzn), via the Comet code refered above.\n",
|
||||
"# All comments are from the MiniZinc code.\n",
|
||||
"# '''\n",
|
||||
"# The sequence of values in array 'x' (which must all be in the range 1..S)\n",
|
||||
"# is accepted by the DFA of 'Q' states with input 1..S and transition\n",
|
||||
"# function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
|
||||
"# (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
|
||||
"# 1..Q). We reserve state 0 to be an always failing state.\n",
|
||||
"# '''\n",
|
||||
"#\n",
|
||||
"# x : IntVar array\n",
|
||||
"# Q : number of states\n",
|
||||
"# S : input_max\n",
|
||||
"# d : transition matrix\n",
|
||||
"# q0: initial state\n",
|
||||
"# F : accepting states\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def regular(x, Q, S, d, q0, F):\n",
|
||||
"\n",
|
||||
" solver = x[0].solver()\n",
|
||||
"\n",
|
||||
" assert Q > 0, 'regular: \"Q\" must be greater than zero'\n",
|
||||
" assert S > 0, 'regular: \"S\" must be greater than zero'\n",
|
||||
"\n",
|
||||
" # d2 is the same as d, except we add one extra transition for\n",
|
||||
" # each possible input; each extra transition is from state zero\n",
|
||||
" # to state zero. This allows us to continue even if we hit a\n",
|
||||
" # non-accepted input.\n",
|
||||
"\n",
|
||||
" # Comet: int d2[0..Q, 1..S]\n",
|
||||
" d2 = []\n",
|
||||
" for i in range(Q + 1):\n",
|
||||
" row = []\n",
|
||||
" for j in range(S):\n",
|
||||
" if i == 0:\n",
|
||||
" row.append(0)\n",
|
||||
" else:\n",
|
||||
" row.append(d[i - 1][j])\n",
|
||||
" d2.append(row)\n",
|
||||
"\n",
|
||||
" d2_flatten = [d2[i][j] for i in range(Q + 1) for j in range(S)]\n",
|
||||
"\n",
|
||||
" # If x has index set m..n, then a[m-1] holds the initial state\n",
|
||||
" # (q0), and a[i+1] holds the state we're in after processing\n",
|
||||
" # x[i]. If a[n] is in F, then we succeed (ie. accept the\n",
|
||||
" # string).\n",
|
||||
" x_range = list(range(0, len(x)))\n",
|
||||
" m = 0\n",
|
||||
" n = len(x)\n",
|
||||
"\n",
|
||||
" a = [solver.IntVar(0, Q + 1, 'a[%i]' % i) for i in range(m, n + 1)]\n",
|
||||
"\n",
|
||||
" # Check that the final state is in F\n",
|
||||
" solver.Add(solver.MemberCt(a[-1], F))\n",
|
||||
" # First state is q0\n",
|
||||
" solver.Add(a[m] == q0)\n",
|
||||
" for i in x_range:\n",
|
||||
" solver.Add(x[i] >= 1)\n",
|
||||
" solver.Add(x[i] <= S)\n",
|
||||
"\n",
|
||||
" # Determine a[i+1]: a[i+1] == d2[a[i], x[i]]\n",
|
||||
" solver.Add(\n",
|
||||
" a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('3 jugs problem using regular constraint')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the DFA (for regular)\n",
|
||||
"n_states = 14\n",
|
||||
"input_max = 15\n",
|
||||
"initial_state = 1 # 0 is for the failing state\n",
|
||||
"accepting_states = [15]\n",
|
||||
"\n",
|
||||
"##\n",
|
||||
"# Manually crafted DFA\n",
|
||||
"# (from the adjacency matrix used in the other models)\n",
|
||||
"##\n",
|
||||
"# transition_fn = [\n",
|
||||
"# # 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5\n",
|
||||
"# [0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], # 1\n",
|
||||
"# [0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 2\n",
|
||||
"# [0, 0, 0, 4, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0], # 3\n",
|
||||
"# [0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # 4\n",
|
||||
"# [0, 0, 0, 0, 0, 6, 0, 0, 9, 0, 0, 0, 0, 0, 0], # 5\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0], # 6\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0], # 7\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15], # 8\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0], # 9\n",
|
||||
"# [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0], # 10\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0], # 11\n",
|
||||
"# [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0], # 12\n",
|
||||
"# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0], # 13\n",
|
||||
"# [0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15], # 14\n",
|
||||
"# # 15\n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# However, the DFA is easy to create from adjacency lists.\n",
|
||||
"#\n",
|
||||
"states = [\n",
|
||||
" [2, 9], # state 1\n",
|
||||
" [3], # state 2\n",
|
||||
" [4, 9], # state 3\n",
|
||||
" [5], # state 4\n",
|
||||
" [6, 9], # state 5\n",
|
||||
" [7], # state 6\n",
|
||||
" [8, 9], # state 7\n",
|
||||
" [15], # state 8\n",
|
||||
" [10], # state 9\n",
|
||||
" [11], # state 10\n",
|
||||
" [12], # state 11\n",
|
||||
" [13], # state 12\n",
|
||||
" [14], # state 13\n",
|
||||
" [15] # state 14\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"transition_fn = []\n",
|
||||
"for i in range(n_states):\n",
|
||||
" row = []\n",
|
||||
" for j in range(1, input_max + 1):\n",
|
||||
" if j in states[i]:\n",
|
||||
" row.append(j)\n",
|
||||
" else:\n",
|
||||
" row.append(0)\n",
|
||||
" transition_fn.append(row)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# The name of the nodes, for printing\n",
|
||||
"# the solution.\n",
|
||||
"#\n",
|
||||
"nodes = [\n",
|
||||
" '8,0,0', # 1 start\n",
|
||||
" '5,0,3', # 2\n",
|
||||
" '5,3,0', # 3\n",
|
||||
" '2,3,3', # 4\n",
|
||||
" '2,5,1', # 5\n",
|
||||
" '7,0,1', # 6\n",
|
||||
" '7,1,0', # 7\n",
|
||||
" '4,1,3', # 8\n",
|
||||
" '3,5,0', # 9\n",
|
||||
" '3,2,3', # 10\n",
|
||||
" '6,2,0', # 11\n",
|
||||
" '6,0,2', # 12\n",
|
||||
" '1,5,2', # 13\n",
|
||||
" '1,4,3', # 14\n",
|
||||
" '4,4,0' # 15 goal\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(1, input_max, 'x[%i]' % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"regular(x, n_states, input_max, transition_fn, initial_state,\n",
|
||||
" accepting_states)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"x_val = []\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" x_val = [1] + [x[i].Value() for i in range(n)]\n",
|
||||
" print('x:', x_val)\n",
|
||||
" for i in range(1, n + 1):\n",
|
||||
" print('%s -> %s' % (nodes[x_val[i - 1] - 1], nodes[x_val[i] - 1]))\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"if num_solutions > 0:\n",
|
||||
" print()\n",
|
||||
" print('num_solutions:', num_solutions)\n",
|
||||
" print('failures:', solver.Failures())\n",
|
||||
" print('branches:', solver.Branches())\n",
|
||||
" print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"# return the solution (or an empty array)\n",
|
||||
"return x_val\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Search for a minimum solution by increasing\n",
|
||||
"# the length of the state array."
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
178
examples/notebook/contrib/a_round_of_golf.ipynb
Normal file
178
examples/notebook/contrib/a_round_of_golf.ipynb
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" A Round of Golf puzzle (Dell Logic Puzzles) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://brownbuffalo.sourceforge.net/RoundOfGolfClues.html\n",
|
||||
" '''\n",
|
||||
" Title: A Round of Golf\n",
|
||||
" Author: Ellen K. Rodehorst\n",
|
||||
" Publication: Dell Favorite Logic Problems\n",
|
||||
" Issue: Summer, 2000\n",
|
||||
" Puzzle #: 9\n",
|
||||
" Stars: 1\n",
|
||||
"\n",
|
||||
" When the Sunny Hills Country Club golf course isn't in use by club members,\n",
|
||||
" of course, it's open to the club's employees. Recently, Jack and three other\n",
|
||||
" workers at the golf course got together on their day off to play a round of\n",
|
||||
" eighteen holes of golf.\n",
|
||||
" Afterward, all four, including Mr. Green, went to the clubhouse to total\n",
|
||||
" their scorecards. Each man works at a different job (one is a short-order\n",
|
||||
" cook), and each shot a different score in the game. No one scored below\n",
|
||||
" 70 or above 85 strokes. From the clues below, can you discover each man's\n",
|
||||
" full name, job and golf score?\n",
|
||||
"\n",
|
||||
" 1. Bill, who is not the maintenance man, plays golf often and had the lowest\n",
|
||||
" score of the foursome.\n",
|
||||
" 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and scored ten\n",
|
||||
" strokes more than the pro-shop clerk.\n",
|
||||
" 3. In some order, Frank and the caddy scored four and seven more strokes than\n",
|
||||
" Mr. Sands.\n",
|
||||
" 4. Mr. Carter thought his score of 78 was one of his better games, even\n",
|
||||
" though Frank's score was lower.\n",
|
||||
" 5. None of the four scored exactly 81 strokes.\n",
|
||||
"\n",
|
||||
" Determine: First Name - Last Name - Job - Score\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the F1 model:\n",
|
||||
" http://www.f1compiler.com/samples/A 20Round 20of 20Golf.f1.html\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/a_round_of_golf.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/a_round_of_golf.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/a_round_of_golf.ecl\n",
|
||||
" * Gecode : http://hakank.org/gecode/a_round_of_golf.cpp\n",
|
||||
" * SICStus : http://hakank.org/sicstus/a_round_of_golf.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"All interval\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"[Jack, Bill, Paul, Frank] = [i for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"last_name = [solver.IntVar(0, n - 1, \"last_name[%i]\" % i) for i in range(n)]\n",
|
||||
"[Green, Clubb, Sands, Carter] = last_name\n",
|
||||
"\n",
|
||||
"job = [solver.IntVar(0, n - 1, \"job[%i]\" % i) for i in range(n)]\n",
|
||||
"[cook, maintenance_man, clerk, caddy] = job\n",
|
||||
"\n",
|
||||
"score = [solver.IntVar(70, 85, \"score[%i]\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(last_name))\n",
|
||||
"solver.Add(solver.AllDifferent(job))\n",
|
||||
"solver.Add(solver.AllDifferent(score))\n",
|
||||
"\n",
|
||||
"# 1. Bill, who is not the maintenance man, plays golf often and had\n",
|
||||
"# the lowest score of the foursome.\n",
|
||||
"solver.Add(Bill != maintenance_man)\n",
|
||||
"solver.Add(score[Bill] < score[Jack])\n",
|
||||
"solver.Add(score[Bill] < score[Paul])\n",
|
||||
"solver.Add(score[Bill] < score[Frank])\n",
|
||||
"\n",
|
||||
"# 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and\n",
|
||||
"# scored ten strokes more than the pro-shop clerk.\n",
|
||||
"solver.Add(Clubb != Paul)\n",
|
||||
"solver.Add(solver.Element(score, Clubb) == solver.Element(score, clerk) + 10)\n",
|
||||
"\n",
|
||||
"# 3. In some order, Frank and the caddy scored four and seven more\n",
|
||||
"# strokes than Mr. Sands.\n",
|
||||
"solver.Add(Frank != caddy)\n",
|
||||
"solver.Add(Frank != Sands)\n",
|
||||
"solver.Add(caddy != Sands)\n",
|
||||
"\n",
|
||||
"b3_a_1 = solver.IsEqualVar(solver.Element(score, Sands) + 4, score[Frank])\n",
|
||||
"b3_a_2 = solver.IsEqualVar(\n",
|
||||
" solver.Element(score, caddy),\n",
|
||||
" solver.Element(score, Sands) + 7)\n",
|
||||
"\n",
|
||||
"b3_b_1 = solver.IsEqualVar(solver.Element(score, Sands) + 7, score[Frank])\n",
|
||||
"b3_b_2 = solver.IsEqualVar(\n",
|
||||
" solver.Element(score, caddy),\n",
|
||||
" solver.Element(score, Sands) + 4)\n",
|
||||
"\n",
|
||||
"solver.Add((b3_a_1 * b3_a_2) + (b3_b_1 * b3_b_2) == 1)\n",
|
||||
"\n",
|
||||
"# 4. Mr. Carter thought his score of 78 was one of his better games,\n",
|
||||
"# even though Frank's score was lower.\n",
|
||||
"solver.Add(Frank != Carter)\n",
|
||||
"solver.Add(solver.Element(score, Carter) == 78)\n",
|
||||
"solver.Add(score[Frank] < solver.Element(score, Carter))\n",
|
||||
"\n",
|
||||
"# 5. None of the four scored exactly 81 strokes.\n",
|
||||
"[solver.Add(score[i] != 81) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(last_name)\n",
|
||||
"solution.Add(job)\n",
|
||||
"solution.Add(score)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(last_name + job + score, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"last_name:\", [last_name[i].Value() for i in range(n)])\n",
|
||||
" print(\"job :\", [job[i].Value() for i in range(n)])\n",
|
||||
" print(\"score :\", [score[i].Value() for i in range(n)])\n",
|
||||
" num_solutions += 1\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
125
examples/notebook/contrib/all_interval.ipynb
Normal file
125
examples/notebook/contrib/all_interval.ipynb
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" All interval problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" CSPLib problem number 7\n",
|
||||
" http://www.cs.st-andrews.ac.uk/~ianm/CSPLib/prob/prob007/index.html\n",
|
||||
" '''\n",
|
||||
" Given the twelve standard pitch-classes (c, c , d, ...), represented by\n",
|
||||
" numbers 0,1,...,11, find a series in which each pitch-class occurs exactly\n",
|
||||
" once and in which the musical intervals between neighbouring notes cover\n",
|
||||
" the full set of intervals from the minor second (1 semitone) to the major\n",
|
||||
" seventh (11 semitones). That is, for each of the intervals, there is a\n",
|
||||
" pair of neigbhouring pitch-classes in the series, between which this\n",
|
||||
" interval appears. The problem of finding such a series can be easily\n",
|
||||
" formulated as an instance of a more general arithmetic problem on Z_n,\n",
|
||||
" the set of integer residues modulo n. Given n in N, find a vector\n",
|
||||
" s = (s_1, ..., s_n), such that (i) s is a permutation of\n",
|
||||
" Z_n = {0,1,...,n-1}; and (ii) the interval vector\n",
|
||||
" v = (|s_2-s_1|, |s_3-s_2|, ... |s_n-s_{n-1}|) is a permutation of\n",
|
||||
" Z_n-{0} = {1,2,...,n-1}. A vector v satisfying these conditions is\n",
|
||||
" called an all-interval series of size n; the problem of finding such\n",
|
||||
" a series is the all-interval series problem of size n. We may also be\n",
|
||||
" interested in finding all possible series of a given size.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/all_interval.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/all_interval.co\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/all_interval.rb\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/all_interval.ecl\n",
|
||||
" * SICStus : http://www.hakank.org/sicstus/all_interval.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"All interval\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print(\"n:\", n)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(1, n, \"x[%i]\" % i) for i in range(n)]\n",
|
||||
"diffs = [solver.IntVar(1, n - 1, \"diffs[%i]\" % i) for i in range(n - 1)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"solver.Add(solver.AllDifferent(diffs))\n",
|
||||
"\n",
|
||||
"for k in range(n - 1):\n",
|
||||
" solver.Add(diffs[k] == abs(x[k + 1] - x[k]))\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"solver.Add(x[0] < x[n - 1])\n",
|
||||
"solver.Add(diffs[0] < diffs[1])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(diffs)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"x:\", [x[i].Value() for i in range(n)])\n",
|
||||
" print(\"diffs:\", [diffs[i].Value() for i in range(n - 1)])\n",
|
||||
" num_solutions += 1\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"n = 12\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
137
examples/notebook/contrib/alldifferent_except_0.ipynb
Normal file
137
examples/notebook/contrib/alldifferent_except_0.ipynb
Normal file
@@ -0,0 +1,137 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" All different except 0 Google CP Solver.\n",
|
||||
"\n",
|
||||
" Decomposition of global constraint alldifferent_except_0.\n",
|
||||
"\n",
|
||||
" From Global constraint catalogue:\n",
|
||||
" http://www.emn.fr/x-info/sdemasse/gccat/Calldifferent_except_0.html\n",
|
||||
" '''\n",
|
||||
" Enforce all variables of the collection VARIABLES to take distinct\n",
|
||||
" values, except those variables that are assigned to 0.\n",
|
||||
"\n",
|
||||
" Example\n",
|
||||
" (<5, 0, 1, 9, 0, 3>)\n",
|
||||
"\n",
|
||||
" The alldifferent_except_0 constraint holds since all the values\n",
|
||||
" (that are different from 0) 5, 1, 9 and 3 are distinct.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet: http://hakank.org/comet/alldifferent_except_0.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/alldifferent_except_0.ecl\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/alldifferent_except_0.eprime\n",
|
||||
" * Gecode: http://hakank.org/gecode/alldifferent_except_0.cpp\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/all_different_except_0.rb\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/alldifferent_except_0.mzn\n",
|
||||
" * SICStus_ http://hakank.org/sicstus/alldifferent_except_0.pl\n",
|
||||
" * Choco: http://hakank.org/choco/AllDifferentExcept0_test.java\n",
|
||||
" * JaCoP: http://hakank.org/JaCoP/AllDifferentExcept0_test.java\n",
|
||||
" * Zinc: http://hakank.org/minizinc/alldifferent_except_0.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Decomposition of alldifferent_except_0\n",
|
||||
"# Thanks to Laurent Perron (Google) for\n",
|
||||
"# suggestions of improvements.\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def alldifferent_except_0(solver, a):\n",
|
||||
" n = len(a)\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(i):\n",
|
||||
" solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# more compact version:\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def alldifferent_except_0_b(solver, a):\n",
|
||||
" n = len(a)\n",
|
||||
" [\n",
|
||||
" solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]))\n",
|
||||
" for i in range(n)\n",
|
||||
" for j in range(i)\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Alldifferent except 0\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"n = 7\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(n)]\n",
|
||||
"# Number of zeros.\n",
|
||||
"z = solver.Sum([x[i] == 0 for i in range(n)]).VarWithName(\"z\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"alldifferent_except_0(solver, x)\n",
|
||||
"\n",
|
||||
"# we require 2 0's\n",
|
||||
"solver.Add(z == 2)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([x[i] for i in range(n)])\n",
|
||||
"solution.Add(z)\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase([x[i] for i in range(n)], solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE), [collector])\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"for s in range(num_solutions):\n",
|
||||
" print(\"x:\", [collector.Value(s, x[i]) for i in range(n)])\n",
|
||||
" print(\"z:\", collector.Value(s, z))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
166
examples/notebook/contrib/alphametic.ipynb
Normal file
166
examples/notebook/contrib/alphametic.ipynb
Normal file
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Generic alphametic solver in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This is a generic alphametic solver.\n",
|
||||
"\n",
|
||||
" Usage:\n",
|
||||
" python alphametic.py\n",
|
||||
" -> solves SEND+MORE=MONEY in base 10\n",
|
||||
"\n",
|
||||
" python alphametic.py 'SEND+MOST=MONEY' 11\n",
|
||||
" -> solver SEND+MOST=MONEY in base 11\n",
|
||||
"\n",
|
||||
" python alphametic.py TEST <base>\n",
|
||||
" -> solve some test problems in base <base>\n",
|
||||
" (defined in test_problems())\n",
|
||||
"\n",
|
||||
" Assumptions:\n",
|
||||
" - we only solves problems of the form\n",
|
||||
" NUMBER<1>+NUMBER<2>...+NUMBER<N-1> = NUMBER<N>\n",
|
||||
" i.e. the last number is the sum\n",
|
||||
" - the only nonletter characters are: +, =, \\d (which are splitted upon)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following model:\n",
|
||||
" * Zinc: http://www.hakank.org/minizinc/alphametic.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"import re\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Send most money\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"print(\"\\nproblem:\", problem_str)\n",
|
||||
"\n",
|
||||
"# convert to array.\n",
|
||||
"problem = re.split(\"[\\s+=]\", problem_str)\n",
|
||||
"\n",
|
||||
"p_len = len(problem)\n",
|
||||
"print(\"base:\", base)\n",
|
||||
"\n",
|
||||
"# create the lookup table: list of (digit : ix)\n",
|
||||
"a = sorted(set(\"\".join(problem)))\n",
|
||||
"n = len(a)\n",
|
||||
"lookup = dict(list(zip(a, list(range(n)))))\n",
|
||||
"\n",
|
||||
"# length of each number\n",
|
||||
"lens = list(map(len, problem))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the digits\n",
|
||||
"x = [solver.IntVar(0, base - 1, \"x[%i]\" % i) for i in range(n)]\n",
|
||||
"# the sums of each number (e.g. the three numbers SEND, MORE, MONEY)\n",
|
||||
"sums = [solver.IntVar(1, 10**(lens[i]) - 1) for i in range(p_len)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"\n",
|
||||
"ix = 0\n",
|
||||
"for prob in problem:\n",
|
||||
" this_len = len(prob)\n",
|
||||
"\n",
|
||||
" # sum all the digits with proper exponents to a number\n",
|
||||
" solver.Add(\n",
|
||||
" sums[ix] == solver.Sum([(base**i) * x[lookup[prob[this_len - i - 1]]]\n",
|
||||
" for i in range(this_len)[::-1]]))\n",
|
||||
" # leading digits must be > 0\n",
|
||||
" solver.Add(x[lookup[prob[0]]] > 0)\n",
|
||||
" ix += 1\n",
|
||||
"\n",
|
||||
"# the last number is the sum of the previous numbers\n",
|
||||
"solver.Add(solver.Sum([sums[i] for i in range(p_len - 1)]) == sums[-1])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(sums)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"\\nsolution #%i\" % num_solutions)\n",
|
||||
" for i in range(n):\n",
|
||||
" print(a[i], \"=\", x[i].Value())\n",
|
||||
" print()\n",
|
||||
" for prob in problem:\n",
|
||||
" for p in prob:\n",
|
||||
" print(p, end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
" for prob in problem:\n",
|
||||
" for p in prob:\n",
|
||||
" print(x[lookup[p]].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print(\"sums:\", [sums[i].Value() for i in range(p_len)])\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print(\"\\nnum_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"def test_problems(base=10):\n",
|
||||
" problems = [\n",
|
||||
" \"SEND+MORE=MONEY\", \"SEND+MOST=MONEY\", \"VINGT+CINQ+CINQ=TRENTE\",\n",
|
||||
" \"EIN+EIN+EIN+EIN=VIER\", \"DONALD+GERALD=ROBERT\",\n",
|
||||
" \"SATURN+URANUS+NEPTUNE+PLUTO+PLANETS\", \"WRONG+WRONG=RIGHT\"\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
" for p in problems:\n",
|
||||
" main(p, base)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"problem = \"SEND+MORE=MONEY\"\n",
|
||||
"base = 10\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
135
examples/notebook/contrib/assignment.ipynb
Normal file
135
examples/notebook/contrib/assignment.ipynb
Normal file
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Assignment problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Winston 'Operations Research', Assignment Problems, page 393f\n",
|
||||
" (generalized version with added test column)\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet : http://www.hakank.org/comet/assignment.co\n",
|
||||
" * ECLiPSE : http://www.hakank.org/eclipse/assignment.ecl\n",
|
||||
" * Gecode : http://www.hakank.org/gecode/assignment.cpp\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/assignment.mzn\n",
|
||||
" * Tailor/Essence': http://www.hakank.org/tailor/assignment.eprime\n",
|
||||
" * SICStus: http://hakank.org/sicstus/assignment.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"total_cost = solver.IntVar(0, 100, \"total_cost\")\n",
|
||||
"x = []\n",
|
||||
"for i in range(rows):\n",
|
||||
" t = []\n",
|
||||
" for j in range(cols):\n",
|
||||
" t.append(solver.IntVar(0, 1, \"x[%i,%i]\" % (i, j)))\n",
|
||||
" x.append(t)\n",
|
||||
"x_flat = [x[i][j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# total_cost\n",
|
||||
"solver.Add(total_cost == solver.Sum(\n",
|
||||
" [solver.ScalProd(x_row, cost_row) for (x_row, cost_row) in zip(x, cost)]))\n",
|
||||
"\n",
|
||||
"# exacly one assignment per row, all rows must be assigned\n",
|
||||
"[\n",
|
||||
" solver.Add(solver.Sum([x[row][j]\n",
|
||||
" for j in range(cols)]) == 1)\n",
|
||||
" for row in range(rows)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# zero or one assignments per column\n",
|
||||
"[\n",
|
||||
" solver.Add(solver.Sum([x[i][col]\n",
|
||||
" for i in range(rows)]) <= 1)\n",
|
||||
" for col in range(cols)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"objective = solver.Minimize(total_cost, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x_flat)\n",
|
||||
"solution.Add(total_cost)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"total_cost:\", total_cost.Value())\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(x[i][j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" for i in range(rows):\n",
|
||||
" print(\"Task:\", i, end=\" \")\n",
|
||||
" for j in range(cols):\n",
|
||||
" if x[i][j].Value() == 1:\n",
|
||||
" print(\" is done by \", j)\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Problem instance\n",
|
||||
"# hakank: I added the fifth column to make it more\n",
|
||||
"# interestingrows = 4\n",
|
||||
"cols = 5\n",
|
||||
"cost = [[14, 5, 8, 7, 15], [2, 12, 6, 5, 3], [7, 8, 3, 9, 7], [2, 4, 6, 10, 1]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
162
examples/notebook/contrib/assignment6_mip.ipynb
Normal file
162
examples/notebook/contrib/assignment6_mip.ipynb
Normal file
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Assignment problem using MIP in Google or-tools.\n",
|
||||
"\n",
|
||||
" From GLPK:s example assign.mod:\n",
|
||||
" '''\n",
|
||||
" The assignment problem is one of the fundamental combinatorial\n",
|
||||
" optimization problems.\n",
|
||||
"\n",
|
||||
" In its most general form, the problem is as follows:\n",
|
||||
"\n",
|
||||
" There are a number of agents and a number of tasks. Any agent can be\n",
|
||||
" assigned to perform any task, incurring some cost that may vary\n",
|
||||
" depending on the agent-task assignment. It is required to perform all\n",
|
||||
" tasks by assigning exactly one agent to each task in such a way that\n",
|
||||
" the total cost of the assignment is minimized.\n",
|
||||
"\n",
|
||||
" (From Wikipedia, the free encyclopedia.)\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the Comet model:\n",
|
||||
" http://www.hakank.org/comet/assignment6.co\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCBC',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# number of agents\n",
|
||||
"m = 8\n",
|
||||
"\n",
|
||||
"# number of tasks\n",
|
||||
"n = 8\n",
|
||||
"\n",
|
||||
"# set of agents\n",
|
||||
"I = list(range(m))\n",
|
||||
"\n",
|
||||
"# set of tasks\n",
|
||||
"J = list(range(n))\n",
|
||||
"\n",
|
||||
"# cost of allocating task j to agent i\n",
|
||||
"# \"\"\"\n",
|
||||
"# These data correspond to an example from [Christofides].\n",
|
||||
"#\n",
|
||||
"# Optimal solution is 76\n",
|
||||
"# \"\"\"\n",
|
||||
"c = [[13, 21, 20, 12, 8, 26, 22, 11], [12, 36, 25, 41, 40, 11, 4, 8],\n",
|
||||
" [35, 32, 13, 36, 26, 21, 13, 37], [34, 54, 7, 8, 12, 22, 11, 40],\n",
|
||||
" [21, 6, 45, 18, 24, 34, 12, 48], [42, 19, 39, 15, 14, 16, 28, 46],\n",
|
||||
" [16, 34, 38, 3, 34, 40, 22, 24], [26, 20, 5, 17, 45, 31, 37, 43]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# For the output: the assignment as task number.\n",
|
||||
"assigned = [solver.IntVar(0, 10000, 'assigned[%i]' % j) for j in J]\n",
|
||||
"\n",
|
||||
"costs = [solver.IntVar(0, 10000, 'costs[%i]' % i) for i in I]\n",
|
||||
"\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(0, 1, 'x[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"# total cost, to be minimized\n",
|
||||
"z = solver.Sum([c[i][j] * x[i, j] for i in I for j in J])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"# each agent can perform at most one task\n",
|
||||
"for i in I:\n",
|
||||
" solver.Add(solver.Sum([x[i, j] for j in J]) <= 1)\n",
|
||||
"\n",
|
||||
"# each task must be assigned exactly to one agent\n",
|
||||
"for j in J:\n",
|
||||
" solver.Add(solver.Sum([x[i, j] for i in I]) == 1)\n",
|
||||
"\n",
|
||||
"# to which task and what cost is person i assigned (for output in MiniZinc)\n",
|
||||
"for i in I:\n",
|
||||
" solver.Add(assigned[i] == solver.Sum([j * x[i, j] for j in J]))\n",
|
||||
" solver.Add(costs[i] == solver.Sum([c[i][j] * x[i, j] for j in J]))\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(z)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('z: ', int(solver.Objective().Value()))\n",
|
||||
"\n",
|
||||
"print('Assigned')\n",
|
||||
"for j in J:\n",
|
||||
" print(int(assigned[j].SolutionValue()), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('Matrix:')\n",
|
||||
"for i in I:\n",
|
||||
" for j in J:\n",
|
||||
" print(int(x[i, j].SolutionValue()), end=' ')\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
101
examples/notebook/contrib/bacp.ipynb
Normal file
101
examples/notebook/contrib/bacp.ipynb
Normal file
@@ -0,0 +1,101 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Pierre Schaus pschaus@gmail.com\n",
|
||||
"#\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",
|
||||
"import argparse\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"parser = argparse.ArgumentParser()\n",
|
||||
"\n",
|
||||
"parser.add_argument(\n",
|
||||
" '--data', default='examples/data/bacp/bacp12.txt', help='path to data file')\n",
|
||||
"\n",
|
||||
"#----------------helper for binpacking posting----------------\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def BinPacking(solver, binvars, weights, loadvars):\n",
|
||||
" \"\"\"post the load constraint on bins.\n",
|
||||
"\n",
|
||||
" constraints forall j: loadvars[j] == sum_i (binvars[i] == j) * weights[i])\n",
|
||||
" \"\"\"\n",
|
||||
" pack = solver.Pack(binvars, len(loadvars))\n",
|
||||
" pack.AddWeightedSumEqualVarDimension(weights, loadvars)\n",
|
||||
" solver.Add(pack)\n",
|
||||
" solver.Add(solver.SumEquality(loadvars, sum(weights)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#------------------------------data reading-------------------\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def ReadData(filename):\n",
|
||||
" \"\"\"Read data from <filename>.\"\"\"\n",
|
||||
" f = open(filename)\n",
|
||||
" nb_courses, nb_periods, min_credit, max_credit, nb_prereqs =\\\n",
|
||||
" [int(nb) for nb in f.readline().split()]\n",
|
||||
" credits = [int(nb) for nb in f.readline().split()]\n",
|
||||
" prereq = [int(nb) for nb in f.readline().split()]\n",
|
||||
" prereq = [(prereq[i * 2], prereq[i * 2 + 1]) for i in range(nb_prereqs)]\n",
|
||||
" return (credits, nb_periods, prereq)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#------------------solver and variable declaration-------------\n",
|
||||
"\n",
|
||||
"credits, nb_periods, prereq = ReadData(args.data)\n",
|
||||
"nb_courses = len(credits)\n",
|
||||
"\n",
|
||||
"solver = pywrapcp.Solver('Balanced Academic Curriculum Problem')\n",
|
||||
"\n",
|
||||
"x = [\n",
|
||||
" solver.IntVar(0, nb_periods - 1, 'x' + str(i)) for i in range(nb_courses)\n",
|
||||
"]\n",
|
||||
"load_vars = [\n",
|
||||
" solver.IntVar(0, sum(credits), 'load_vars' + str(i))\n",
|
||||
" for i in range(nb_periods)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#-------------------post of the constraints--------------\n",
|
||||
"\n",
|
||||
"# Bin Packing.\n",
|
||||
"BinPacking(solver, x, credits, load_vars)\n",
|
||||
"# Add dependencies.\n",
|
||||
"for i, j in prereq:\n",
|
||||
" solver.Add(x[i] < x[j])\n",
|
||||
"\n",
|
||||
"#----------------Objective-------------------------------\n",
|
||||
"\n",
|
||||
"objective_var = solver.Max(load_vars)\n",
|
||||
"objective = solver.Minimize(objective_var, 1)\n",
|
||||
"\n",
|
||||
"#------------start the search and optimization-----------\n",
|
||||
"\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"search_log = solver.SearchLog(100000, objective_var)\n",
|
||||
"solver.Solve(db, [objective, search_log])\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
152
examples/notebook/contrib/blending.ipynb
Normal file
152
examples/notebook/contrib/blending.ipynb
Normal file
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Blending problem in Google or-tools.\n",
|
||||
"\n",
|
||||
" From the OPL model blending.mod.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCBC',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"NbMetals = 3\n",
|
||||
"NbRaw = 2\n",
|
||||
"NbScrap = 2\n",
|
||||
"NbIngo = 1\n",
|
||||
"Metals = list(range(NbMetals))\n",
|
||||
"Raws = list(range(NbRaw))\n",
|
||||
"Scraps = list(range(NbScrap))\n",
|
||||
"Ingos = list(range(NbIngo))\n",
|
||||
"\n",
|
||||
"CostMetal = [22, 10, 13]\n",
|
||||
"CostRaw = [6, 5]\n",
|
||||
"CostScrap = [7, 8]\n",
|
||||
"CostIngo = [9]\n",
|
||||
"Low = [0.05, 0.30, 0.60]\n",
|
||||
"Up = [0.10, 0.40, 0.80]\n",
|
||||
"PercRaw = [[0.20, 0.01], [0.05, 0], [0.05, 0.30]]\n",
|
||||
"PercScrap = [[0, 0.01], [0.60, 0], [0.40, 0.70]]\n",
|
||||
"PercIngo = [[0.10], [0.45], [0.45]]\n",
|
||||
"Alloy = 71\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"p = [solver.NumVar(0, solver.Infinity(), 'p[%i]' % i) for i in Metals]\n",
|
||||
"r = [solver.NumVar(0, solver.Infinity(), 'r[%i]' % i) for i in Raws]\n",
|
||||
"s = [solver.NumVar(0, solver.Infinity(), 's[%i]' % i) for i in Scraps]\n",
|
||||
"ii = [solver.IntVar(0, solver.Infinity(), 'ii[%i]' % i) for i in Ingos]\n",
|
||||
"metal = [\n",
|
||||
" solver.NumVar(Low[j] * Alloy, Up[j] * Alloy, 'metal[%i]' % j)\n",
|
||||
" for j in Metals\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"z = solver.NumVar(0, solver.Infinity(), 'z')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"solver.Add(z == solver.Sum([CostMetal[i] * p[i] for i in Metals]) +\n",
|
||||
" solver.Sum([CostRaw[i] * r[i] for i in Raws]) +\n",
|
||||
" solver.Sum([CostScrap[i] * s[i] for i in Scraps]) +\n",
|
||||
" solver.Sum([CostIngo[i] * ii[i] for i in Ingos]))\n",
|
||||
"\n",
|
||||
"for j in Metals:\n",
|
||||
" solver.Add(\n",
|
||||
" metal[j] == p[j] + solver.Sum([PercRaw[j][k] * r[k] for k in Raws]) +\n",
|
||||
" solver.Sum([PercScrap[j][k] * s[k] for k in Scraps]) +\n",
|
||||
" solver.Sum([PercIngo[j][k] * ii[k] for k in Ingos]))\n",
|
||||
"\n",
|
||||
"solver.Add(solver.Sum(metal) == Alloy)\n",
|
||||
"\n",
|
||||
"objective = solver.Minimize(z)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('z = ', solver.Objective().Value())\n",
|
||||
"print('Metals')\n",
|
||||
"for i in Metals:\n",
|
||||
" print(p[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('Raws')\n",
|
||||
"for i in Raws:\n",
|
||||
" print(r[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('Scraps')\n",
|
||||
"for i in Scraps:\n",
|
||||
" print(s[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('Ingos')\n",
|
||||
"for i in Ingos:\n",
|
||||
" print(ii[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('Metals')\n",
|
||||
"for i in Metals:\n",
|
||||
" print(metal[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
147
examples/notebook/contrib/broken_weights.ipynb
Normal file
147
examples/notebook/contrib/broken_weights.ipynb
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Broken weights problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://www.mathlesstraveled.com/?p=701\n",
|
||||
" '''\n",
|
||||
" Here's a fantastic problem I recently heard. Apparently it was first\n",
|
||||
" posed by Claude Gaspard Bachet de Meziriac in a book of arithmetic problems\n",
|
||||
" published in 1612, and can also be found in Heinrich Dorrie's 100\n",
|
||||
" Great Problems of Elementary Mathematics.\n",
|
||||
"\n",
|
||||
" A merchant had a forty pound measuring weight that broke\n",
|
||||
" into four pieces as the result of a fall. When the pieces were\n",
|
||||
" subsequently weighed, it was found that the weight of each piece\n",
|
||||
" was a whole number of pounds and that the four pieces could be\n",
|
||||
" used to weigh every integral weight between 1 and 40 pounds. What\n",
|
||||
" were the weights of the pieces?\n",
|
||||
"\n",
|
||||
" Note that since this was a 17th-century merchant, he of course used a\n",
|
||||
" balance scale to weigh things. So, for example, he could use a 1-pound\n",
|
||||
" weight and a 4-pound weight to weigh a 3-pound object, by placing the\n",
|
||||
" 3-pound object and 1-pound weight on one side of the scale, and\n",
|
||||
" the 4-pound weight on the other side.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following problems:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/broken_weights.mzn\n",
|
||||
" * ECLiPSE: http://www.hakank.org/eclipse/broken_weights.ecl\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/broken_weights.cpp\n",
|
||||
" * Comet: http://hakank.org/comet/broken_weights.co\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Broken weights')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print('total weight (m):', m)\n",
|
||||
"print('number of pieces (n):', n)\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"weights = [solver.IntVar(1, m, 'weights[%i]' % j) for j in range(n)]\n",
|
||||
"x = {}\n",
|
||||
"for i in range(m):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(-1, 1, 'x[%i,%i]' % (i, j))\n",
|
||||
"x_flat = [x[i, j] for i in range(m) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"for j in range(1, n):\n",
|
||||
" solver.Add(weights[j - 1] < weights[j])\n",
|
||||
"\n",
|
||||
"solver.Add(solver.SumEquality(weights, m))\n",
|
||||
"\n",
|
||||
"# Check that all weights from 1 to 40 can be made.\n",
|
||||
"#\n",
|
||||
"# Since all weights can be on either side\n",
|
||||
"# of the side of the scale we allow either\n",
|
||||
"# -1, 0, or 1 or the weights, assuming that\n",
|
||||
"# -1 is the weights on the left and 1 is on the right.\n",
|
||||
"#\n",
|
||||
"for i in range(m):\n",
|
||||
" solver.Add(i + 1 == solver.Sum([weights[j] * x[i, j] for j in range(n)]))\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(weights[n - 1], 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(weights + x_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"search_log = solver.SearchLog(1)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('weights: ', end=' ')\n",
|
||||
" for w in [weights[j].Value() for j in range(n)]:\n",
|
||||
" print('%3i ' % w, end=' ')\n",
|
||||
" print()\n",
|
||||
" print('-' * 30)\n",
|
||||
" for i in range(m):\n",
|
||||
" print('weight %2i:' % (i + 1), end=' ')\n",
|
||||
" for j in range(n):\n",
|
||||
" print('%3i ' % x[i, j].Value(), end=' ')\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures :', solver.Failures())\n",
|
||||
"print('branches :', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"m = 40\n",
|
||||
"n = 4\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
118
examples/notebook/contrib/bus_schedule.ipynb
Normal file
118
examples/notebook/contrib/bus_schedule.ipynb
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Bus scheduling in Google CP Solver.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Problem from Taha \"Introduction to Operations Research\", page 58.\n",
|
||||
"\n",
|
||||
" This is a slightly more general model than Taha's.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/bus_scheduling.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/bus_schedule.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/bus_schedule.ecl\n",
|
||||
" * Gecode : http://www.hakank.org/gecode/bus_schedule.cpp\n",
|
||||
" * Tailor/Essence' : http://www.hakank.org/tailor/bus_schedule.eprime\n",
|
||||
" * SICStus: http://hakank.org/sicstus/bus_schedule.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Bus scheduling\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"time_slots = 6\n",
|
||||
"demands = [8, 10, 7, 12, 4, 4]\n",
|
||||
"max_num = sum(demands)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = [solver.IntVar(0, max_num, \"x%i\" % i) for i in range(time_slots)]\n",
|
||||
"num_buses = solver.IntVar(0, max_num, \"num_buses\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(num_buses == solver.Sum(x))\n",
|
||||
"\n",
|
||||
"# Meet the demands for this and the next time slot\n",
|
||||
"for i in range(time_slots - 1):\n",
|
||||
" solver.Add(x[i] + x[i + 1] >= demands[i])\n",
|
||||
"\n",
|
||||
"# The demand \"around the clock\"\n",
|
||||
"solver.Add(x[time_slots - 1] + x[0] == demands[time_slots - 1])\n",
|
||||
"\n",
|
||||
"if num_buses_check > 0:\n",
|
||||
" solver.Add(num_buses == num_buses_check)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(num_buses)\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"cargs = [collector]\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"if num_buses_check == 0:\n",
|
||||
" objective = solver.Minimize(num_buses, 1)\n",
|
||||
" cargs.extend([objective])\n",
|
||||
"\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n",
|
||||
" cargs)\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"num_buses_check_value = 0\n",
|
||||
"for s in range(num_solutions):\n",
|
||||
" print(\"x:\", [collector.Value(s, x[i]) for i in range(len(x))], end=\" \")\n",
|
||||
" num_buses_check_value = collector.Value(s, num_buses)\n",
|
||||
" print(\" num_buses:\", num_buses_check_value)\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"print()\n",
|
||||
"if num_buses_check == 0:\n",
|
||||
" return num_buses_check_value\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
149
examples/notebook/contrib/car.ipynb
Normal file
149
examples/notebook/contrib/car.ipynb
Normal file
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Car sequencing in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This model is based on the car sequencing model in\n",
|
||||
" Pascal Van Hentenryck\n",
|
||||
" 'The OPL Optimization Programming Language', page 184ff.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/car.mzn\n",
|
||||
" * Comet: http://hakank.org/comet/car.co\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Car sequence\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"nbCars = 6\n",
|
||||
"nbOptions = 5\n",
|
||||
"nbSlots = 10\n",
|
||||
"\n",
|
||||
"Cars = list(range(nbCars))\n",
|
||||
"Options = list(range(nbOptions))\n",
|
||||
"Slots = list(range(nbSlots))\n",
|
||||
"\n",
|
||||
"# car 0 1 2 3 4 5\n",
|
||||
"demand = [1, 1, 2, 2, 2, 2]\n",
|
||||
"\n",
|
||||
"option = [\n",
|
||||
" # car 0 1 2 3 4 5\n",
|
||||
" [1, 0, 0, 0, 1, 1], # option 1\n",
|
||||
" [0, 0, 1, 1, 0, 1], # option 2\n",
|
||||
" [1, 0, 0, 0, 1, 0], # option 3\n",
|
||||
" [1, 1, 0, 1, 0, 0], # option 4\n",
|
||||
" [0, 0, 1, 0, 0, 0] # option 5\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"capacity = [(1, 2), (2, 3), (1, 3), (2, 5), (1, 5)]\n",
|
||||
"\n",
|
||||
"optionDemand = [\n",
|
||||
" sum([demand[j] * option[i][j] for j in Cars]) for i in Options\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"slot = [solver.IntVar(0, nbCars - 1, \"slot[%i]\" % i) for i in Slots]\n",
|
||||
"setup = {}\n",
|
||||
"for i in Options:\n",
|
||||
" for j in Slots:\n",
|
||||
" setup[(i, j)] = solver.IntVar(0, 1, \"setup[%i,%i]\" % (i, j))\n",
|
||||
"setup_flat = [setup[i, j] for i in Options for j in Slots]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for c in Cars:\n",
|
||||
" b = [solver.IsEqualCstVar(slot[s], c) for s in Slots]\n",
|
||||
" solver.Add(solver.Sum(b) == demand[c])\n",
|
||||
"\n",
|
||||
"for o in Options:\n",
|
||||
" for s in range(0, nbSlots - capacity[o][1] + 1):\n",
|
||||
" b = [setup[o, j] for j in range(s, s + capacity[o][1] - 1)]\n",
|
||||
" solver.Add(solver.Sum(b) <= capacity[o][0])\n",
|
||||
"\n",
|
||||
"for o in Options:\n",
|
||||
" for s in Slots:\n",
|
||||
" solver.Add(setup[(o, s)] == solver.Element(option[o], slot[s]))\n",
|
||||
"\n",
|
||||
"for o in Options:\n",
|
||||
" for i in range(optionDemand[o]):\n",
|
||||
" s_range = list(range(0, nbSlots - (i + 1) * capacity[o][1]))\n",
|
||||
" ss = [setup[o, s] for s in s_range]\n",
|
||||
" cc = optionDemand[o] - (i + 1) * capacity[o][0]\n",
|
||||
" if len(ss) > 0 and cc >= 0:\n",
|
||||
" solver.Add(solver.Sum(ss) >= cc)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(slot + setup_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"slot:%s\" % \",\".join([str(slot[i].Value()) for i in Slots]))\n",
|
||||
" print(\"setup:\")\n",
|
||||
" for o in Options:\n",
|
||||
" print(\"%i/%i:\" % (capacity[o][0], capacity[o][1]), end=\" \")\n",
|
||||
" for s in Slots:\n",
|
||||
" print(setup[o, s].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
" if num_solutions >= num_sol:\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"num_sol = 3\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
58
examples/notebook/contrib/check_dependencies.ipynb
Normal file
58
examples/notebook/contrib/check_dependencies.ipynb
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import logging, sys, inspect\n",
|
||||
"from os.path import dirname, abspath\n",
|
||||
"from optparse import OptionParser\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def log_error_and_exit(error_message):\n",
|
||||
" logging.error(error_message)\n",
|
||||
" raise SystemExit\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#try to import setuptools\n",
|
||||
"try:\n",
|
||||
" from setuptools import setup, Extension\n",
|
||||
" from setuptools.command import easy_install\n",
|
||||
"except ImportError:\n",
|
||||
" log_error_and_exit(\"\"\"setuptools is not installed for \\\"\"\"\" + sys.executable +\n",
|
||||
" \"\"\"\\\"\n",
|
||||
"Follow this link for installing instructions :\n",
|
||||
"https://pypi.python.org/pypi/setuptools\n",
|
||||
"make sure you use \\\"\"\"\" + sys.executable + \"\"\"\\\" during the installation\"\"\")\n",
|
||||
"\n",
|
||||
"from pkg_resources import parse_version\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def notinstalled(modulename):\n",
|
||||
" return modulename + \"\"\" could not be imported for \\\"\"\"\" + sys.executable + \"\"\"\\\"\n",
|
||||
"Set PYTHONPATH to the output of this command \\\"make print-OR_TOOLS_PYTHONPATH\\\" before running the examples\"\"\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def wrong_module(module_file, modulename):\n",
|
||||
" return \"\"\"\n",
|
||||
"The python examples are not importing the \"\"\" + modulename + \"\"\" module from the sources.\n",
|
||||
"Remove the site-package that contains \\\"\"\"\" + module_file + \"\"\"\\\", either manually or by using pip, and rerun this script again.\"\"\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Returns the n_th parent of file\n",
|
||||
"def n_dirname(n, file):\n",
|
||||
" directory = file\n",
|
||||
" for x in range(0, n):\n",
|
||||
" directory = dirname(directory)\n",
|
||||
" return directory\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
140
examples/notebook/contrib/circuit.ipynb
Normal file
140
examples/notebook/contrib/circuit.ipynb
Normal file
@@ -0,0 +1,140 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Decomposition of the circuit constraint in Google CP Solver.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Cf Global constraint catalog:\n",
|
||||
" http://www.emn.fr/x-info/sdemasse/gccat/Ccircuit.html\n",
|
||||
"\n",
|
||||
" Solution of n=4:\n",
|
||||
" x: [2, 0, 3, 1]\n",
|
||||
" x: [3, 0, 1, 2]\n",
|
||||
" x: [1, 3, 0, 2]\n",
|
||||
" x: [3, 2, 0, 1]\n",
|
||||
" x: [1, 2, 3, 0]\n",
|
||||
" x: [2, 3, 1, 0]\n",
|
||||
"\n",
|
||||
" The 'orbit' method that is used here is based on some\n",
|
||||
" observations on permutation orbits.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/circuit_test.mzn\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/circuit_orbit.mzn\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# circuit(x)\n",
|
||||
"# constraints x to be an circuit\n",
|
||||
"#\n",
|
||||
"# Note: This assumes that x is has the domain 0..len(x)-1,\n",
|
||||
"# i.e. 0-based.\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def circuit(solver, x):\n",
|
||||
" n = len(x)\n",
|
||||
" z = [solver.IntVar(0, n - 1, \"z%i\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
" solver.Add(solver.AllDifferent(x))\n",
|
||||
" solver.Add(solver.AllDifferent(z))\n",
|
||||
"\n",
|
||||
" # put the orbit of x[0] in in z[0..n-1]\n",
|
||||
" solver.Add(z[0] == x[0])\n",
|
||||
" for i in range(1, n - 1):\n",
|
||||
" # The following constraint give the error\n",
|
||||
" # \"TypeError: list indices must be integers, not IntVar\"\n",
|
||||
" # solver.Add(z[i] == x[z[i-1]])\n",
|
||||
"\n",
|
||||
" # solution: use Element instead\n",
|
||||
" solver.Add(z[i] == solver.Element(x, z[i - 1]))\n",
|
||||
"\n",
|
||||
" #\n",
|
||||
" # Note: At least one of the following two constraint must be set.\n",
|
||||
" #\n",
|
||||
" # may not be 0 for i < n-1\n",
|
||||
" for i in range(1, n - 1):\n",
|
||||
" solver.Add(z[i] != 0)\n",
|
||||
"\n",
|
||||
" # when i = n-1 it must be 0\n",
|
||||
" solver.Add(z[n - 1] == 0)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Send most money\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"print(\"n:\", n)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"# Note: domain should be 0..n-1\n",
|
||||
"x = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"circuit(solver, x)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n",
|
||||
" [collector])\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"for s in range(num_solutions):\n",
|
||||
" print(\"x:\", [collector.Value(s, x[i]) for i in range(len(x))])\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"n = 5\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
115
examples/notebook/contrib/coins3.ipynb
Normal file
115
examples/notebook/contrib/coins3.ipynb
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Coin application in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From 'Constraint Logic Programming using ECLiPSe'\n",
|
||||
" pages 99f and 234 ff.\n",
|
||||
" The solution in ECLiPSe is at page 236.\n",
|
||||
"\n",
|
||||
" '''\n",
|
||||
" What is the minimum number of coins that allows one to pay _exactly_\n",
|
||||
" any amount smaller than one Euro? Recall that there are six different\n",
|
||||
" euro cents, of denomination 1, 2, 5, 10, 20, 50\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/coins3.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/coins3.co\n",
|
||||
" * Gecode : http://hakank.org/gecode/coins3.cpp\n",
|
||||
" * SICStus : http://hakank.org/sicstus/coins3.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Coins\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 6 # number of different coins\n",
|
||||
"variables = [1, 2, 5, 10, 25, 50]\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = [solver.IntVar(0, 99, \"x%i\" % i) for i in range(n)]\n",
|
||||
"num_coins = solver.IntVar(0, 99, \"num_coins\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# number of used coins, to be minimized\n",
|
||||
"solver.Add(num_coins == solver.Sum(x))\n",
|
||||
"\n",
|
||||
"# Check that all changes from 1 to 99 can be made.\n",
|
||||
"for j in range(1, 100):\n",
|
||||
" tmp = [solver.IntVar(0, 99, \"b%i\" % i) for i in range(n)]\n",
|
||||
" solver.Add(solver.ScalProd(tmp, variables) == j)\n",
|
||||
" [solver.Add(tmp[i] <= x[i]) for i in range(n)]\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(num_coins, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(num_coins)\n",
|
||||
"solution.AddObjective(num_coins)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"x: \", [x[i].Value() for i in range(n)])\n",
|
||||
" print(\"num_coins:\", num_coins.Value())\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
129
examples/notebook/contrib/coins_grid.ipynb
Normal file
129
examples/notebook/contrib/coins_grid.ipynb
Normal file
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
" Coins grid problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Problem from\n",
|
||||
" Tony Hurlimann: \"A coin puzzle - SVOR-contest 2007\"\n",
|
||||
" http://www.svor.ch/competitions/competition2007/AsroContestSolution.pdf\n",
|
||||
" '''\n",
|
||||
" In a quadratic grid (or a larger chessboard) with 31x31 cells, one should\n",
|
||||
" place coins in such a way that the following conditions are fulfilled:\n",
|
||||
" 1. In each row exactly 14 coins must be placed.\n",
|
||||
" 2. In each column exactly 14 coins must be placed.\n",
|
||||
" 3. The sum of the quadratic horizontal distance from the main diagonal\n",
|
||||
" of all cells containing a coin must be as small as possible.\n",
|
||||
" 4. In each cell at most one coin can be placed.\n",
|
||||
" The description says to place 14x31 = 434 coins on the chessboard each row\n",
|
||||
" containing 14 coins and each column also containing 14 coins.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Cf the LPL model:\n",
|
||||
" http://diuflx71.unifr.ch/lpl/GetModel?name=/puzzles/coin\n",
|
||||
"\n",
|
||||
" Note: Laurent Perron helped me to improve this model.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/coins_grid.eprime\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/coins_grid.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/coins_grid.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/coins_grid.zinc\n",
|
||||
" * Choco: http://hakank.org/choco/CoinsGrid.java\n",
|
||||
" * Comet: http://hakank.org/comet/coins_grid.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/coins_grid.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/coins_grid.cpp\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/coins_grid.rb\n",
|
||||
" * JaCoP: http://hakank.org/JaCoP/CoinsGrid.java\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Coins grid\")\n",
|
||||
"# data\n",
|
||||
"\n",
|
||||
"print(\"n: \", n)\n",
|
||||
"print(\"c: \", c)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[(i, j)] = solver.BoolVar(\"x %i %i\" % (i, j))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# sum rows/columns == c\n",
|
||||
"for i in range(n):\n",
|
||||
" solver.Add(solver.SumEquality([x[(i, j)] for j in range(n)], c)) # sum rows\n",
|
||||
" solver.Add(solver.SumEquality([x[(j, i)] for j in range(n)], c)) # sum cols\n",
|
||||
"\n",
|
||||
"# quadratic horizonal distance var\n",
|
||||
"objective_var = solver.Sum(\n",
|
||||
" [x[(i, j)] * (i - j) * (i - j) for i in range(n) for j in range(n)])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(objective_var, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([x[(i, j)] for i in range(n) for j in range(n)])\n",
|
||||
"solution.AddObjective(objective_var)\n",
|
||||
"\n",
|
||||
"# last solutions\n",
|
||||
"collector = solver.LastSolutionCollector(solution)\n",
|
||||
"search_log = solver.SearchLog(1000000, objective_var)\n",
|
||||
"restart = solver.ConstantRestart(300)\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase([x[(i, j)] for i in range(n) for j in range(n)],\n",
|
||||
" solver.CHOOSE_RANDOM, solver.ASSIGN_MAX_VALUE),\n",
|
||||
" [collector, search_log, objective])\n",
|
||||
"\n",
|
||||
"print(\"objective:\", collector.ObjectiveValue(0))\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(collector.Value(0, x[(i, j)]), end=\" \")\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
113
examples/notebook/contrib/coins_grid_mip.ipynb
Normal file
113
examples/notebook/contrib/coins_grid_mip.ipynb
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Coins grid problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Problem from\n",
|
||||
" Tony Hurlimann: \"A coin puzzle - SVOR-contest 2007\"\n",
|
||||
" http://www.svor.ch/competitions/competition2007/AsroContestSolution.pdf\n",
|
||||
" '''\n",
|
||||
" In a quadratic grid (or a larger chessboard) with 31x31 cells, one should\n",
|
||||
" place coins in such a way that the following conditions are fulfilled:\n",
|
||||
" 1. In each row exactly 14 coins must be placed.\n",
|
||||
" 2. In each column exactly 14 coins must be placed.\n",
|
||||
" 3. The sum of the quadratic horizontal distance from the main diagonal\n",
|
||||
" of all cells containing a coin must be as small as possible.\n",
|
||||
" 4. In each cell at most one coin can be placed.\n",
|
||||
" The description says to place 14x31 = 434 coins on the chessboard each row\n",
|
||||
" containing 14 coins and each column also containing 14 coins.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" This is a MIP version of\n",
|
||||
" http://www.hakank.org/google_or_tools/coins_grid.py\n",
|
||||
" and use\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"# using CBC\n",
|
||||
"solver = pywraplp.Solver('CoinsGridCBC',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"# Using CLP\n",
|
||||
"# solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
"# pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"n = 31 # the grid size\n",
|
||||
"c = 14 # number of coins per row/column\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[(i, j)] = solver.IntVar(0, 1, 'x[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# sum rows/columns == c\n",
|
||||
"for i in range(n):\n",
|
||||
" solver.Add(solver.Sum([x[(i, j)] for j in range(n)]) == c) # sum rows\n",
|
||||
" solver.Add(solver.Sum([x[(j, i)] for j in range(n)]) == c) # sum cols\n",
|
||||
"\n",
|
||||
"# quadratic horizonal distance var\n",
|
||||
"objective_var = solver.Sum(\n",
|
||||
" [x[(i, j)] * (i - j) * (i - j) for i in range(n) for j in range(n)])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(objective_var)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" # int representation\n",
|
||||
" print(int(x[(i, j)].SolutionValue()), end=' ')\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"# print 'iterations:', solver.Iterations()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
152
examples/notebook/contrib/coloring_ip.ipynb
Normal file
152
examples/notebook/contrib/coloring_ip.ipynb
Normal file
@@ -0,0 +1,152 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Simple coloring problem using MIP in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Inspired by the GLPK:s model color.mod\n",
|
||||
" '''\n",
|
||||
" COLOR, Graph Coloring Problem\n",
|
||||
"\n",
|
||||
" Written in GNU MathProg by Andrew Makhorin <mao@mai2.rcnet.ru>\n",
|
||||
"\n",
|
||||
" Given an undirected loopless graph G = (V, E), where V is a set of\n",
|
||||
" nodes, E <= V x V is a set of arcs, the Graph Coloring Problem is to\n",
|
||||
" find a mapping (coloring) F: V -> C, where C = {1, 2, ... } is a set\n",
|
||||
" of colors whose cardinality is as small as possible, such that\n",
|
||||
" F(i) != F(j) for every arc (i,j) in E, that is adjacent nodes must\n",
|
||||
" be assigned different colors.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the MiniZinc model:\n",
|
||||
" http://www.hakank.org/minizinc/coloring_ip.mzn\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" # using GLPK\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# max number of colors\n",
|
||||
"# [we know that 4 suffices for normal maps]\n",
|
||||
"nc = 5\n",
|
||||
"\n",
|
||||
"# number of nodes\n",
|
||||
"n = 11\n",
|
||||
"# set of nodes\n",
|
||||
"V = list(range(n))\n",
|
||||
"\n",
|
||||
"num_edges = 20\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Neighbours\n",
|
||||
"#\n",
|
||||
"# This data correspond to the instance myciel3.col from:\n",
|
||||
"# http://mat.gsia.cmu.edu/COLOR/instances.html\n",
|
||||
"#\n",
|
||||
"# Note: 1-based (adjusted below)\n",
|
||||
"E = [[1, 2], [1, 4], [1, 7], [1, 9], [2, 3], [2, 6], [2, 8], [3, 5], [3, 7],\n",
|
||||
" [3, 10], [4, 5], [4, 6], [4, 10], [5, 8], [5, 9], [6, 11], [7, 11],\n",
|
||||
" [8, 11], [9, 11], [10, 11]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# x[i,c] = 1 means that node i is assigned color c\n",
|
||||
"x = {}\n",
|
||||
"for v in V:\n",
|
||||
" for j in range(nc):\n",
|
||||
" x[v, j] = solver.IntVar(0, 1, 'v[%i,%i]' % (v, j))\n",
|
||||
"\n",
|
||||
"# u[c] = 1 means that color c is used, i.e. assigned to some node\n",
|
||||
"u = [solver.IntVar(0, 1, 'u[%i]' % i) for i in range(nc)]\n",
|
||||
"\n",
|
||||
"# number of colors used, to minimize\n",
|
||||
"obj = solver.Sum(u)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# each node must be assigned exactly one color\n",
|
||||
"for i in V:\n",
|
||||
" solver.Add(solver.Sum([x[i, c] for c in range(nc)]) == 1)\n",
|
||||
"\n",
|
||||
"# adjacent nodes cannot be assigned the same color\n",
|
||||
"# (and adjust to 0-based)\n",
|
||||
"for i in range(num_edges):\n",
|
||||
" for c in range(nc):\n",
|
||||
" solver.Add(x[E[i][0] - 1, c] + x[E[i][1] - 1, c] <= u[c])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(obj)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('number of colors:', int(solver.Objective().Value()))\n",
|
||||
"print('colors used:', [int(u[i].SolutionValue()) for i in range(nc)])\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"for v in V:\n",
|
||||
" print('v%i' % v, ' color ', end=' ')\n",
|
||||
" for c in range(nc):\n",
|
||||
" if int(x[v, c].SolutionValue()) == 1:\n",
|
||||
" print(c)\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('WallTime:', solver.WallTime())\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
119
examples/notebook/contrib/combinatorial_auction2.ipynb
Normal file
119
examples/notebook/contrib/combinatorial_auction2.ipynb
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\"\"\"Combinatorial auction in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This is a more general model for the combinatorial example\n",
|
||||
" in the Numberjack Tutorial, pages 9 and 24 (slides 19/175 and\n",
|
||||
" 51/175).\n",
|
||||
"\n",
|
||||
" The original and more talkative model is here:\n",
|
||||
" http://www.hakank.org/numberjack/combinatorial_auction.py\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/combinatorial_auction.mzn\n",
|
||||
" * Gecode: http://hakank.org/gecode/combinatorial_auction.cpp\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from collections import *\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Problem\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"N = 5\n",
|
||||
"\n",
|
||||
"# the items for each bid\n",
|
||||
"items = [\n",
|
||||
" [0, 1], # A,B\n",
|
||||
" [0, 2], # A, C\n",
|
||||
" [1, 3], # B,D\n",
|
||||
" [1, 2, 3], # B,C,D\n",
|
||||
" [0] # A\n",
|
||||
"]\n",
|
||||
"# collect the bids for each item\n",
|
||||
"items_t = defaultdict(list)\n",
|
||||
"\n",
|
||||
"# [items_t.setdefault(j,[]).append(i) for i in range(N) for j in items[i] ]\n",
|
||||
"# nicer:\n",
|
||||
"[items_t[j].append(i) for i in range(N) for j in items[i]]\n",
|
||||
"\n",
|
||||
"bid_amount = [10, 20, 30, 40, 14]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"X = [solver.BoolVar(\"x%i\" % i) for i in range(N)]\n",
|
||||
"obj = solver.IntVar(0, 100, \"obj\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(obj == solver.ScalProd(X, bid_amount))\n",
|
||||
"for item in items_t:\n",
|
||||
" solver.Add(solver.Sum([X[bid] for bid in items_t[item]]) <= 1)\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Maximize(obj, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(X)\n",
|
||||
"solution.Add(obj)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(X, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"X:\", [X[i].Value() for i in range(N)])\n",
|
||||
" print(\"obj:\", obj.Value())\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
187
examples/notebook/contrib/contiguity_regular.ipynb
Normal file
187
examples/notebook/contrib/contiguity_regular.ipynb
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Global constraint contiguity using regularin Google CP Solver.\n",
|
||||
"\n",
|
||||
" This is a decomposition of the global constraint\n",
|
||||
" global contiguity.\n",
|
||||
"\n",
|
||||
" From Global Constraint Catalogue\n",
|
||||
" http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html\n",
|
||||
" '''\n",
|
||||
" Enforce all variables of the VARIABLES collection to be assigned to 0 or 1.\n",
|
||||
" In addition, all variables assigned to value 1 appear contiguously.\n",
|
||||
"\n",
|
||||
" Example:\n",
|
||||
" (<0, 1, 1, 0>)\n",
|
||||
"\n",
|
||||
" The global_contiguity constraint holds since the sequence 0 1 1 0 contains\n",
|
||||
" no more than one group of contiguous 1.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following model:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/contiguity_regular.mzn\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Global constraint regular\n",
|
||||
"#\n",
|
||||
"# This is a translation of MiniZinc's regular constraint (defined in\n",
|
||||
"# lib/zinc/globals.mzn), via the Comet code refered above.\n",
|
||||
"# All comments are from the MiniZinc code.\n",
|
||||
"# '''\n",
|
||||
"# The sequence of values in array 'x' (which must all be in the range 1..S)\n",
|
||||
"# is accepted by the DFA of 'Q' states with input 1..S and transition\n",
|
||||
"# function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
|
||||
"# (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
|
||||
"# 1..Q). We reserve state 0 to be an always failing state.\n",
|
||||
"# '''\n",
|
||||
"#\n",
|
||||
"# x : IntVar array\n",
|
||||
"# Q : number of states\n",
|
||||
"# S : input_max\n",
|
||||
"# d : transition matrix\n",
|
||||
"# q0: initial state\n",
|
||||
"# F : accepting states\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def regular(x, Q, S, d, q0, F):\n",
|
||||
"\n",
|
||||
" solver = x[0].solver()\n",
|
||||
"\n",
|
||||
" assert Q > 0, 'regular: \"Q\" must be greater than zero'\n",
|
||||
" assert S > 0, 'regular: \"S\" must be greater than zero'\n",
|
||||
"\n",
|
||||
" # d2 is the same as d, except we add one extra transition for\n",
|
||||
" # each possible input; each extra transition is from state zero\n",
|
||||
" # to state zero. This allows us to continue even if we hit a\n",
|
||||
" # non-accepted input.\n",
|
||||
"\n",
|
||||
" # Comet: int d2[0..Q, 1..S]\n",
|
||||
" d2 = []\n",
|
||||
" for i in range(Q + 1):\n",
|
||||
" row = []\n",
|
||||
" for j in range(S):\n",
|
||||
" if i == 0:\n",
|
||||
" row.append(0)\n",
|
||||
" else:\n",
|
||||
" row.append(d[i - 1][j])\n",
|
||||
" d2.append(row)\n",
|
||||
"\n",
|
||||
" d2_flatten = [d2[i][j] for i in range(Q + 1) for j in range(S)]\n",
|
||||
"\n",
|
||||
" # If x has index set m..n, then a[m-1] holds the initial state\n",
|
||||
" # (q0), and a[i+1] holds the state we're in after processing\n",
|
||||
" # x[i]. If a[n] is in F, then we succeed (ie. accept the\n",
|
||||
" # string).\n",
|
||||
" x_range = list(range(0, len(x)))\n",
|
||||
" m = 0\n",
|
||||
" n = len(x)\n",
|
||||
"\n",
|
||||
" a = [solver.IntVar(0, Q + 1, 'a[%i]' % i) for i in range(m, n + 1)]\n",
|
||||
"\n",
|
||||
" # Check that the final state is in F\n",
|
||||
" solver.Add(solver.MemberCt(a[-1], F))\n",
|
||||
" # First state is q0\n",
|
||||
" solver.Add(a[m] == q0)\n",
|
||||
" for i in x_range:\n",
|
||||
" solver.Add(x[i] >= 1)\n",
|
||||
" solver.Add(x[i] <= S)\n",
|
||||
"\n",
|
||||
" # Determine a[i+1]: a[i+1] == d2[a[i], x[i]]\n",
|
||||
" solver.Add(\n",
|
||||
" a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Global contiguity using regular')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"# the DFA (for regular)\n",
|
||||
"n_states = 3\n",
|
||||
"input_max = 2\n",
|
||||
"initial_state = 1 # 0 is for the failing state\n",
|
||||
"\n",
|
||||
"# all states are accepting states\n",
|
||||
"accepting_states = [1, 2, 3]\n",
|
||||
"\n",
|
||||
"# The regular expression 0*1*0*\n",
|
||||
"transition_fn = [\n",
|
||||
" [1, 2], # state 1 (start): input 0 -> state 1, input 1 -> state 2 i.e. 0*\n",
|
||||
" [3, 2], # state 2: 1*\n",
|
||||
" [3, 0], # state 3: 0*\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"n = 7\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# We use 1..2 and subtract 1 in the solution\n",
|
||||
"reg_input = [solver.IntVar(1, 2, 'x[%i]' % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"regular(reg_input, n_states, input_max, transition_fn, initial_state,\n",
|
||||
" accepting_states)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(reg_input, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" # Note: here we subract 1 from the solution\n",
|
||||
" print('reg_input:', [int(reg_input[i].Value() - 1) for i in range(n)])\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('wall_time:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
178
examples/notebook/contrib/costas_array.ipynb
Normal file
178
examples/notebook/contrib/costas_array.ipynb
Normal file
@@ -0,0 +1,178 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Costas array in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://mathworld.wolfram.com/CostasArray.html:\n",
|
||||
" '''\n",
|
||||
" An order-n Costas array is a permutation on {1,...,n} such\n",
|
||||
" that the distances in each row of the triangular difference\n",
|
||||
" table are distinct. For example, the permutation {1,3,4,2,5}\n",
|
||||
" has triangular difference table {2,1,-2,3}, {3,-1,1}, {1,2},\n",
|
||||
" and {4}. Since each row contains no duplications, the permutation\n",
|
||||
" is therefore a Costas array.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Also see\n",
|
||||
" http://en.wikipedia.org/wiki/Costas_array\n",
|
||||
"\n",
|
||||
" About this model:\n",
|
||||
" This model is based on Barry O'Sullivan's model:\n",
|
||||
" http://www.g12.cs.mu.oz.au/mzn/costas_array/CostasArray.mzn\n",
|
||||
"\n",
|
||||
" and my small changes in\n",
|
||||
" http://hakank.org/minizinc/costas_array.mzn\n",
|
||||
"\n",
|
||||
" Since there is no symmetry breaking of the order of the Costas\n",
|
||||
" array it gives all the solutions for a specific length of\n",
|
||||
" the array, e.g. those listed in\n",
|
||||
" http://mathworld.wolfram.com/CostasArray.html\n",
|
||||
"\n",
|
||||
" 1 1 (1)\n",
|
||||
" 2 2 (1, 2), (2,1)\n",
|
||||
" 3 4 (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2)\n",
|
||||
" 4 12 (1, 2, 4, 3), (1, 3, 4, 2), (1, 4, 2, 3), (2, 1, 3, 4),\n",
|
||||
" (2, 3, 1, 4), (2, 4, 3, 1), (3, 1, 2, 4), (3, 2, 4, 1),\n",
|
||||
" (3, 4, 2, 1), (4, 1, 3, 2), (4, 2, 1, 3), (4, 3, 1, 2)\n",
|
||||
" ....\n",
|
||||
"\n",
|
||||
" See http://www.research.att.com/~njas/sequences/A008404\n",
|
||||
" for the number of solutions for n=1..\n",
|
||||
" 1, 2, 4, 12, 40, 116, 200, 444, 760, 2160, 4368, 7852, 12828,\n",
|
||||
" 17252, 19612, 21104, 18276, 15096, 10240, 6464, 3536, 2052,\n",
|
||||
" 872, 200, 88, 56, 204,...\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Costas array\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print(\"n:\", n)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"costas = [solver.IntVar(1, n, \"costas[%i]\" % i) for i in range(n)]\n",
|
||||
"differences = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" differences[(i, j)] = solver.IntVar(-n + 1, n - 1,\n",
|
||||
" \"differences[%i,%i]\" % (i, j))\n",
|
||||
"differences_flat = [differences[i, j] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# Fix the values in the lower triangle in the\n",
|
||||
"# difference matrix to -n+1. This removes variants\n",
|
||||
"# of the difference matrix for the the same Costas array.\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(i + 1):\n",
|
||||
" solver.Add(differences[i, j] == -n + 1)\n",
|
||||
"\n",
|
||||
"# hakank: All the following constraints are from\n",
|
||||
"# Barry O'Sullivans's original model.\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(costas))\n",
|
||||
"\n",
|
||||
"# \"How do the positions in the Costas array relate\n",
|
||||
"# to the elements of the distance triangle.\"\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if i < j:\n",
|
||||
" solver.Add(differences[(i, j)] == costas[j] - costas[j - i - 1])\n",
|
||||
"\n",
|
||||
"# \"All entries in a particular row of the difference\n",
|
||||
"# triangle must be distint.\"\n",
|
||||
"for i in range(n - 2):\n",
|
||||
" solver.Add(\n",
|
||||
" solver.AllDifferent([differences[i, j] for j in range(n) if j > i]))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# \"All the following are redundant - only here to speed up search.\"\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# \"We can never place a 'token' in the same row as any other.\"\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if i < j:\n",
|
||||
" solver.Add(differences[i, j] != 0)\n",
|
||||
"\n",
|
||||
"for k in range(2, n):\n",
|
||||
" for l in range(2, n):\n",
|
||||
" if k < l:\n",
|
||||
" solver.Add(differences[k - 2, l - 1] + differences[k, l] ==\n",
|
||||
" differences[k - 1, l - 1] + differences[k - 1, l])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(costas + differences_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"costas:\", [costas[i].Value() for i in range(n)])\n",
|
||||
" print(\"differences:\")\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" v = differences[i, j].Value()\n",
|
||||
" if v == -n + 1:\n",
|
||||
" print(\" \", end=\" \")\n",
|
||||
" else:\n",
|
||||
" print(\"%2d\" % v, end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"n = 6\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
153
examples/notebook/contrib/covering_opl.ipynb
Normal file
153
examples/notebook/contrib/covering_opl.ipynb
Normal file
@@ -0,0 +1,153 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Set covering problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This example is from the OPL example covering.mod\n",
|
||||
" '''\n",
|
||||
" Consider selecting workers to build a house. The construction of a\n",
|
||||
" house can be divided into a number of tasks, each requiring a number of\n",
|
||||
" skills (e.g., plumbing or masonry). A worker may or may not perform a\n",
|
||||
" task, depending on skills. In addition, each worker can be hired for a\n",
|
||||
" cost that also depends on his qualifications. The problem consists of\n",
|
||||
" selecting a set of workers to perform all the tasks, while minimizing the\n",
|
||||
" cost. This is known as a set-covering problem. The key idea in modeling\n",
|
||||
" a set-covering problem as an integer program is to associate a 0/1\n",
|
||||
" variable with each worker to represent whether the worker is hired.\n",
|
||||
" To make sure that all the tasks are performed, it is sufficient to\n",
|
||||
" choose at least one worker by task. This constraint can be expressed by a\n",
|
||||
" simple linear inequality.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Solution from the OPL model (1-based)\n",
|
||||
" '''\n",
|
||||
" Optimal solution found with objective: 14\n",
|
||||
" crew= {23 25 26}\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Solution from this model (0-based):\n",
|
||||
" '''\n",
|
||||
" Total cost 14\n",
|
||||
" We should hire these workers: 22 24 25\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet: http://hakank.org/comet/covering_opl.co\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/covering_opl.mzn\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/covering_opl.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/covering_opl.cpp\n",
|
||||
" * SICStus: http://hakank.org/sicstus/covering_opl.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Set covering\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"nb_workers = 32\n",
|
||||
"Workers = list(range(nb_workers))\n",
|
||||
"num_tasks = 15\n",
|
||||
"Tasks = list(range(num_tasks))\n",
|
||||
"\n",
|
||||
"# Which worker is qualified for each task.\n",
|
||||
"# Note: This is 1-based and will be made 0-base below.\n",
|
||||
"Qualified = [[1, 9, 19, 22, 25, 28, 31],\n",
|
||||
" [2, 12, 15, 19, 21, 23, 27, 29, 30, 31, 32],\n",
|
||||
" [3, 10, 19, 24, 26, 30, 32], [4, 21, 25, 28, 32],\n",
|
||||
" [5, 11, 16, 22, 23, 27, 31], [6, 20, 24, 26, 30, 32],\n",
|
||||
" [7, 12, 17, 25, 30, 31], [8, 17, 20, 22, 23],\n",
|
||||
" [9, 13, 14, 26, 29, 30, 31], [10, 21, 25, 31, 32],\n",
|
||||
" [14, 15, 18, 23, 24, 27, 30, 32], [18, 19, 22, 24, 26, 29, 31],\n",
|
||||
" [11, 20, 25, 28, 30, 32], [16, 19, 23, 31],\n",
|
||||
" [9, 18, 26, 28, 31, 32]]\n",
|
||||
"\n",
|
||||
"Cost = [\n",
|
||||
" 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,\n",
|
||||
" 5, 6, 6, 6, 7, 8, 9\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"Hire = [solver.IntVar(0, 1, \"Hire[%i]\" % w) for w in Workers]\n",
|
||||
"total_cost = solver.IntVar(0, nb_workers * sum(Cost), \"total_cost\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(total_cost == solver.ScalProd(Hire, Cost))\n",
|
||||
"\n",
|
||||
"for j in Tasks:\n",
|
||||
" # Sum the cost for hiring the qualified workers\n",
|
||||
" # (also, make 0-base)\n",
|
||||
" b = solver.Sum([Hire[c - 1] for c in Qualified[j]])\n",
|
||||
" solver.Add(b >= 1)\n",
|
||||
"\n",
|
||||
"# objective: Minimize total cost\n",
|
||||
"objective = solver.Minimize(total_cost, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(Hire, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"Total cost\", total_cost.Value())\n",
|
||||
" print(\"We should hire these workers: \", end=\" \")\n",
|
||||
" for w in Workers:\n",
|
||||
" if Hire[w].Value() == 1:\n",
|
||||
" print(w, end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
219
examples/notebook/contrib/crew.ipynb
Normal file
219
examples/notebook/contrib/crew.ipynb
Normal file
@@ -0,0 +1,219 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Crew allocation problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Gecode example crew\n",
|
||||
" examples/crew.cc\n",
|
||||
" '''\n",
|
||||
" * Example: Airline crew allocation\n",
|
||||
" *\n",
|
||||
" * Assign 20 flight attendants to 10 flights. Each flight needs a certain\n",
|
||||
" * number of cabin crew, and they have to speak certain languages.\n",
|
||||
" * Every cabin crew member has two flights off after an attended flight.\n",
|
||||
" *\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/crew.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/crew.co\n",
|
||||
" * ECLiPSe : http://hakank.org/eclipse/crew.ecl\n",
|
||||
" * SICStus : http://hakank.org/sicstus/crew.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Crew\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"names = [\n",
|
||||
" \"Tom\", \"David\", \"Jeremy\", \"Ron\", \"Joe\", \"Bill\", \"Fred\", \"Bob\", \"Mario\",\n",
|
||||
" \"Ed\", \"Carol\", \"Janet\", \"Tracy\", \"Marilyn\", \"Carolyn\", \"Cathy\", \"Inez\",\n",
|
||||
" \"Jean\", \"Heather\", \"Juliet\"\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"num_persons = len(names) # number of persons\n",
|
||||
"\n",
|
||||
"attributes = [\n",
|
||||
" # steward, hostess, french, spanish, german\n",
|
||||
" [1, 0, 0, 0, 1], # Tom = 1\n",
|
||||
" [1, 0, 0, 0, 0], # David = 2\n",
|
||||
" [1, 0, 0, 0, 1], # Jeremy = 3\n",
|
||||
" [1, 0, 0, 0, 0], # Ron = 4\n",
|
||||
" [1, 0, 0, 1, 0], # Joe = 5\n",
|
||||
" [1, 0, 1, 1, 0], # Bill = 6\n",
|
||||
" [1, 0, 0, 1, 0], # Fred = 7\n",
|
||||
" [1, 0, 0, 0, 0], # Bob = 8\n",
|
||||
" [1, 0, 0, 1, 1], # Mario = 9\n",
|
||||
" [1, 0, 0, 0, 0], # Ed = 10\n",
|
||||
" [0, 1, 0, 0, 0], # Carol = 11\n",
|
||||
" [0, 1, 0, 0, 0], # Janet = 12\n",
|
||||
" [0, 1, 0, 0, 0], # Tracy = 13\n",
|
||||
" [0, 1, 0, 1, 1], # Marilyn = 14\n",
|
||||
" [0, 1, 0, 0, 0], # Carolyn = 15\n",
|
||||
" [0, 1, 0, 0, 0], # Cathy = 16\n",
|
||||
" [0, 1, 1, 1, 1], # Inez = 17\n",
|
||||
" [0, 1, 1, 0, 0], # Jean = 18\n",
|
||||
" [0, 1, 0, 1, 1], # Heather = 19\n",
|
||||
" [0, 1, 1, 0, 0] # Juliet = 20\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# The columns are in the following order:\n",
|
||||
"# staff : Overall number of cabin crew needed\n",
|
||||
"# stewards : How many stewards are required\n",
|
||||
"# hostesses : How many hostesses are required\n",
|
||||
"# french : How many French speaking employees are required\n",
|
||||
"# spanish : How many Spanish speaking employees are required\n",
|
||||
"# german : How many German speaking employees are required\n",
|
||||
"required_crew = [\n",
|
||||
" [4, 1, 1, 1, 1, 1], # Flight 1\n",
|
||||
" [5, 1, 1, 1, 1, 1], # Flight 2\n",
|
||||
" [5, 1, 1, 1, 1, 1], # ..\n",
|
||||
" [6, 2, 2, 1, 1, 1],\n",
|
||||
" [7, 3, 3, 1, 1, 1],\n",
|
||||
" [4, 1, 1, 1, 1, 1],\n",
|
||||
" [5, 1, 1, 1, 1, 1],\n",
|
||||
" [6, 1, 1, 1, 1, 1],\n",
|
||||
" [6, 2, 2, 1, 1, 1], # ...\n",
|
||||
" [7, 3, 3, 1, 1, 1] # Flight 10\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"num_flights = len(required_crew) # number of flights\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"crew = {}\n",
|
||||
"for i in range(num_flights):\n",
|
||||
" for j in range(num_persons):\n",
|
||||
" crew[(i, j)] = solver.IntVar(0, 1, \"crew[%i,%i]\" % (i, j))\n",
|
||||
"crew_flat = [\n",
|
||||
" crew[(i, j)] for i in range(num_flights) for j in range(num_persons)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# number of working persons\n",
|
||||
"num_working = solver.IntVar(1, num_persons, \"num_working\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# number of working persons\n",
|
||||
"solver.Add(num_working == solver.Sum([\n",
|
||||
" solver.IsGreaterOrEqualCstVar(\n",
|
||||
" solver.Sum([crew[(f, p)]\n",
|
||||
" for f in range(num_flights)]), 1)\n",
|
||||
" for p in range(num_persons)\n",
|
||||
"]))\n",
|
||||
"\n",
|
||||
"for f in range(num_flights):\n",
|
||||
" # size of crew\n",
|
||||
" tmp = [crew[(f, i)] for i in range(num_persons)]\n",
|
||||
" solver.Add(solver.Sum(tmp) == required_crew[f][0])\n",
|
||||
"\n",
|
||||
" # attributes and requirements\n",
|
||||
" for j in range(5):\n",
|
||||
" tmp = [attributes[i][j] * crew[(f, i)] for i in range(num_persons)]\n",
|
||||
" solver.Add(solver.Sum(tmp) >= required_crew[f][j + 1])\n",
|
||||
"\n",
|
||||
"# after a flight, break for at least two flights\n",
|
||||
"for f in range(num_flights - 2):\n",
|
||||
" for i in range(num_persons):\n",
|
||||
" solver.Add(crew[f, i] + crew[f + 1, i] + crew[f + 2, i] <= 1)\n",
|
||||
"\n",
|
||||
"# extra contraint: all must work at least two of the flights\n",
|
||||
"# for i in range(num_persons):\n",
|
||||
"# [solver.Add(solver.Sum([crew[f,i] for f in range(num_flights)]) >= 2) ]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(crew_flat)\n",
|
||||
"solution.Add(num_working)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(crew_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# result\n",
|
||||
"#\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"Solution #%i\" % num_solutions)\n",
|
||||
" print(\"Number working:\", num_working.Value())\n",
|
||||
" for i in range(num_flights):\n",
|
||||
" for j in range(num_persons):\n",
|
||||
" print(crew[i, j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print(\"Flights:\")\n",
|
||||
" for flight in range(num_flights):\n",
|
||||
" print(\"Flight\", flight, \"persons:\", end=\" \")\n",
|
||||
" for person in range(num_persons):\n",
|
||||
" if crew[flight, person].Value() == 1:\n",
|
||||
" print(names[person], end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print(\"Crew:\")\n",
|
||||
" for person in range(num_persons):\n",
|
||||
" print(\"%-10s flights\" % names[person], end=\" \")\n",
|
||||
" for flight in range(num_flights):\n",
|
||||
" if crew[flight, person].Value() == 1:\n",
|
||||
" print(flight, end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" if num_solutions >= sols:\n",
|
||||
" break\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"num_solutions_to_show = 1\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
207
examples/notebook/contrib/crossword2.ipynb
Normal file
207
examples/notebook/contrib/crossword2.ipynb
Normal file
@@ -0,0 +1,207 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Crosswords in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This is a standard example for constraint logic programming. See e.g.\n",
|
||||
"\n",
|
||||
" http://www.cis.temple.edu/~ingargio/cis587/readings/constraints.html\n",
|
||||
" '''\n",
|
||||
" We are to complete the puzzle\n",
|
||||
"\n",
|
||||
" 1 2 3 4 5\n",
|
||||
" +---+---+---+---+---+ Given the list of words:\n",
|
||||
" 1 | 1 | | 2 | | 3 | AFT LASER\n",
|
||||
" +---+---+---+---+---+ ALE LEE\n",
|
||||
" 2 | # | # | | # | | EEL LINE\n",
|
||||
" +---+---+---+---+---+ HEEL SAILS\n",
|
||||
" 3 | # | 4 | | 5 | | HIKE SHEET\n",
|
||||
" +---+---+---+---+---+ HOSES STEER\n",
|
||||
" 4 | 6 | # | 7 | | | KEEL TIE\n",
|
||||
" +---+---+---+---+---+ KNOT\n",
|
||||
" 5 | 8 | | | | |\n",
|
||||
" +---+---+---+---+---+\n",
|
||||
" 6 | | # | # | | # | The numbers 1,2,3,4,5,6,7,8 in the crossword\n",
|
||||
" +---+---+---+---+---+ puzzle correspond to the words\n",
|
||||
" that will start at those locations.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" The model was inspired by Sebastian Brand's Array Constraint cross word\n",
|
||||
" example\n",
|
||||
" http://www.cs.mu.oz.au/~sbrand/project/ac/\n",
|
||||
" http://www.cs.mu.oz.au/~sbrand/project/ac/examples.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Also, see the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/crossword.mzn\n",
|
||||
" * Comet: http://www.hakank.org/comet/crossword.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/crossword2.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/crossword2.cpp\n",
|
||||
" * SICStus: http://hakank.org/sicstus/crossword2.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/crossword2.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Problem\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"alpha = \"_abcdefghijklmnopqrstuvwxyz\"\n",
|
||||
"a = 1\n",
|
||||
"b = 2\n",
|
||||
"c = 3\n",
|
||||
"d = 4\n",
|
||||
"e = 5\n",
|
||||
"f = 6\n",
|
||||
"g = 7\n",
|
||||
"h = 8\n",
|
||||
"i = 9\n",
|
||||
"j = 10\n",
|
||||
"k = 11\n",
|
||||
"l = 12\n",
|
||||
"m = 13\n",
|
||||
"n = 14\n",
|
||||
"o = 15\n",
|
||||
"p = 16\n",
|
||||
"q = 17\n",
|
||||
"r = 18\n",
|
||||
"s = 19\n",
|
||||
"t = 20\n",
|
||||
"u = 21\n",
|
||||
"v = 22\n",
|
||||
"w = 23\n",
|
||||
"x = 24\n",
|
||||
"y = 25\n",
|
||||
"z = 26\n",
|
||||
"\n",
|
||||
"num_words = 15\n",
|
||||
"word_len = 5\n",
|
||||
"AA = [\n",
|
||||
" [h, o, s, e, s], # HOSES\n",
|
||||
" [l, a, s, e, r], # LASER\n",
|
||||
" [s, a, i, l, s], # SAILS\n",
|
||||
" [s, h, e, e, t], # SHEET\n",
|
||||
" [s, t, e, e, r], # STEER\n",
|
||||
" [h, e, e, l, 0], # HEEL\n",
|
||||
" [h, i, k, e, 0], # HIKE\n",
|
||||
" [k, e, e, l, 0], # KEEL\n",
|
||||
" [k, n, o, t, 0], # KNOT\n",
|
||||
" [l, i, n, e, 0], # LINE\n",
|
||||
" [a, f, t, 0, 0], # AFT\n",
|
||||
" [a, l, e, 0, 0], # ALE\n",
|
||||
" [e, e, l, 0, 0], # EEL\n",
|
||||
" [l, e, e, 0, 0], # LEE\n",
|
||||
" [t, i, e, 0, 0] # TIE\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"num_overlapping = 12\n",
|
||||
"overlapping = [\n",
|
||||
" [0, 2, 1, 0], # s\n",
|
||||
" [0, 4, 2, 0], # s\n",
|
||||
" [3, 1, 1, 2], # i\n",
|
||||
" [3, 2, 4, 0], # k\n",
|
||||
" [3, 3, 2, 2], # e\n",
|
||||
" [6, 0, 1, 3], # l\n",
|
||||
" [6, 1, 4, 1], # e\n",
|
||||
" [6, 2, 2, 3], # e\n",
|
||||
" [7, 0, 5, 1], # l\n",
|
||||
" [7, 2, 1, 4], # s\n",
|
||||
" [7, 3, 4, 2], # e\n",
|
||||
" [7, 4, 2, 4] # r\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"n = 8\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"A = {}\n",
|
||||
"for I in range(num_words):\n",
|
||||
" for J in range(word_len):\n",
|
||||
" A[(I, J)] = solver.IntVar(0, 26, \"A(%i,%i)\" % (I, J))\n",
|
||||
"\n",
|
||||
"A_flat = [A[(I, J)] for I in range(num_words) for J in range(word_len)]\n",
|
||||
"E = [solver.IntVar(0, num_words, \"E%i\" % I) for I in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(E))\n",
|
||||
"\n",
|
||||
"for I in range(num_words):\n",
|
||||
" for J in range(word_len):\n",
|
||||
" solver.Add(A[(I, J)] == AA[I][J])\n",
|
||||
"\n",
|
||||
"for I in range(num_overlapping):\n",
|
||||
" # This is what I would do:\n",
|
||||
" # solver.Add(A[(E[overlapping[I][0]], overlapping[I][1])] == A[(E[overlapping[I][2]], overlapping[I][3])])\n",
|
||||
"\n",
|
||||
" # But we must use Element explicitly\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Element(A_flat, E[overlapping[I][0]] * word_len +\n",
|
||||
" overlapping[I][1]) == solver\n",
|
||||
" .Element(A_flat, E[overlapping[I][2]] * word_len + overlapping[I][3]))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(E)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(E + A_flat, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(E)\n",
|
||||
" print_solution(A, E, alpha, n, word_len)\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"def print_solution(A, E, alpha, n, word_len):\n",
|
||||
" for ee in range(n):\n",
|
||||
" print(\"%i: (%2i)\" % (ee, E[ee].Value()), end=\" \")\n",
|
||||
" print(\"\".join(\n",
|
||||
" [\"%s\" % (alpha[A[ee, ii].Value()]) for ii in range(word_len)]))\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
126
examples/notebook/contrib/crypta.ipynb
Normal file
126
examples/notebook/contrib/crypta.ipynb
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Cryptarithmetic puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Prolog benchmark problem GNU Prolog (crypta.pl)\n",
|
||||
" '''\n",
|
||||
" Name : crypta.pl\n",
|
||||
" Title : crypt-arithmetic\n",
|
||||
" Original Source: P. Van Hentenryck's book\n",
|
||||
" Adapted by : Daniel Diaz - INRIA France\n",
|
||||
" Date : September 1992\n",
|
||||
"\n",
|
||||
" Solve the operation:\n",
|
||||
"\n",
|
||||
" B A I J J A J I I A H F C F E B B J E A\n",
|
||||
" + D H F G A B C D I D B I F F A G F E J E\n",
|
||||
" -----------------------------------------\n",
|
||||
" = G J E G A C D D H F A F J B F I H E E F\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet: http://hakank.org/comet/crypta.co\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/crypta.mzn\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/crypta.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/crypta.cpp\n",
|
||||
" * SICStus: http://hakank.org/sicstus/crypta.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Crypta\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"LD = [solver.IntVar(0, 9, \"LD[%i]\" % i) for i in range(0, 10)]\n",
|
||||
"A, B, C, D, E, F, G, H, I, J = LD\n",
|
||||
"\n",
|
||||
"Sr1 = solver.IntVar(0, 1, \"Sr1\")\n",
|
||||
"Sr2 = solver.IntVar(0, 1, \"Sr2\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(LD))\n",
|
||||
"solver.Add(B >= 1)\n",
|
||||
"solver.Add(D >= 1)\n",
|
||||
"solver.Add(G >= 1)\n",
|
||||
"\n",
|
||||
"solver.Add(A + 10 * E + 100 * J + 1000 * B + 10000 * B + 100000 * E +\n",
|
||||
" 1000000 * F + E + 10 * J + 100 * E + 1000 * F + 10000 * G +\n",
|
||||
" 100000 * A + 1000000 * F == F + 10 * E + 100 * E + 1000 * H +\n",
|
||||
" 10000 * I + 100000 * F + 1000000 * B + 10000000 * Sr1)\n",
|
||||
"\n",
|
||||
"solver.Add(C + 10 * F + 100 * H + 1000 * A + 10000 * I + 100000 * I +\n",
|
||||
" 1000000 * J + F + 10 * I + 100 * B + 1000 * D + 10000 * I +\n",
|
||||
" 100000 * D + 1000000 * C + Sr1 == J + 10 * F + 100 * A + 1000 * F +\n",
|
||||
" 10000 * H + 100000 * D + 1000000 * D + 10000000 * Sr2)\n",
|
||||
"\n",
|
||||
"solver.Add(A + 10 * J + 100 * J + 1000 * I + 10000 * A + 100000 * B + B +\n",
|
||||
" 10 * A + 100 * G + 1000 * F + 10000 * H + 100000 * D + Sr2 == C +\n",
|
||||
" 10 * A + 100 * G + 1000 * E + 10000 * J + 100000 * G)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(LD, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"str = \"ABCDEFGHIJ\"\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" for (letter, val) in [(str[i], LD[i].Value()) for i in range(len(LD))]:\n",
|
||||
" print(\"%s: %i\" % (letter, val))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
148
examples/notebook/contrib/crypto.ipynb
Normal file
148
examples/notebook/contrib/crypto.ipynb
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Crypto problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Prolog benchmark problem GNU Prolog (crypta.pl)\n",
|
||||
" '''\n",
|
||||
" Name : crypta.pl\n",
|
||||
" Title : crypt-arithmetic\n",
|
||||
" Original Source: P. Van Hentenryck's book\n",
|
||||
" Adapted by : Daniel Diaz - INRIA France\n",
|
||||
" Date : September 1992\n",
|
||||
"\n",
|
||||
" Solve the operation:\n",
|
||||
"\n",
|
||||
" B A I J J A J I I A H F C F E B B J E A\n",
|
||||
" + D H F G A B C D I D B I F F A G F E J E\n",
|
||||
" -----------------------------------------\n",
|
||||
" = G J E G A C D D H F A F J B F I H E E F\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/crypta.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/crypta.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/crypta.ecl\n",
|
||||
" * SICStus : http://hakank.org/sicstus/crypta.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Crypto problem\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"num_letters = 26\n",
|
||||
"\n",
|
||||
"BALLET = 45\n",
|
||||
"CELLO = 43\n",
|
||||
"CONCERT = 74\n",
|
||||
"FLUTE = 30\n",
|
||||
"FUGUE = 50\n",
|
||||
"GLEE = 66\n",
|
||||
"JAZZ = 58\n",
|
||||
"LYRE = 47\n",
|
||||
"OBOE = 53\n",
|
||||
"OPERA = 65\n",
|
||||
"POLKA = 59\n",
|
||||
"QUARTET = 50\n",
|
||||
"SAXOPHONE = 134\n",
|
||||
"SCALE = 51\n",
|
||||
"SOLO = 37\n",
|
||||
"SONG = 61\n",
|
||||
"SOPRANO = 82\n",
|
||||
"THEME = 72\n",
|
||||
"VIOLIN = 100\n",
|
||||
"WALTZ = 34\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"LD = [solver.IntVar(1, num_letters, \"LD[%i]\" % i) for i in range(num_letters)]\n",
|
||||
"A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z = LD\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(LD))\n",
|
||||
"solver.Add(B + A + L + L + E + T == BALLET)\n",
|
||||
"solver.Add(C + E + L + L + O == CELLO)\n",
|
||||
"solver.Add(C + O + N + C + E + R + T == CONCERT)\n",
|
||||
"solver.Add(F + L + U + T + E == FLUTE)\n",
|
||||
"solver.Add(F + U + G + U + E == FUGUE)\n",
|
||||
"solver.Add(G + L + E + E == GLEE)\n",
|
||||
"solver.Add(J + A + Z + Z == JAZZ)\n",
|
||||
"solver.Add(L + Y + R + E == LYRE)\n",
|
||||
"solver.Add(O + B + O + E == OBOE)\n",
|
||||
"solver.Add(O + P + E + R + A == OPERA)\n",
|
||||
"solver.Add(P + O + L + K + A == POLKA)\n",
|
||||
"solver.Add(Q + U + A + R + T + E + T == QUARTET)\n",
|
||||
"solver.Add(S + A + X + O + P + H + O + N + E == SAXOPHONE)\n",
|
||||
"solver.Add(S + C + A + L + E == SCALE)\n",
|
||||
"solver.Add(S + O + L + O == SOLO)\n",
|
||||
"solver.Add(S + O + N + G == SONG)\n",
|
||||
"solver.Add(S + O + P + R + A + N + O == SOPRANO)\n",
|
||||
"solver.Add(T + H + E + M + E == THEME)\n",
|
||||
"solver.Add(V + I + O + L + I + N == VIOLIN)\n",
|
||||
"solver.Add(W + A + L + T + Z == WALTZ)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(LD, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_CENTER_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"str = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\"\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" for (letter, val) in [(str[i], LD[i].Value()) for i in range(num_letters)]:\n",
|
||||
" print(\"%s: %i\" % (letter, val))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
138
examples/notebook/contrib/curious_set_of_integers.ipynb
Normal file
138
examples/notebook/contrib/curious_set_of_integers.ipynb
Normal file
@@ -0,0 +1,138 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Crypto problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Martin Gardner (February 1967):\n",
|
||||
" '''\n",
|
||||
" The integers 1,3,8, and 120 form a set with a remarkable property: the\n",
|
||||
" product of any two integers is one less than a perfect square. Find\n",
|
||||
" a fifth number that can be added to the set without destroying\n",
|
||||
" this property.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Solution: The number is 0.\n",
|
||||
"\n",
|
||||
" There are however other sets of five numbers with this property.\n",
|
||||
" Here are the one in the range of 0.10000:\n",
|
||||
" [0, 1, 3, 8, 120]\n",
|
||||
" [0, 1, 3, 120, 1680]\n",
|
||||
" [0, 1, 8, 15, 528]\n",
|
||||
" [0, 1, 8, 120, 4095]\n",
|
||||
" [0, 1, 15, 24, 1520]\n",
|
||||
" [0, 1, 24, 35, 3480]\n",
|
||||
" [0, 1, 35, 48, 6888]\n",
|
||||
" [0, 2, 4, 12, 420]\n",
|
||||
" [0, 2, 12, 24, 2380]\n",
|
||||
" [0, 2, 24, 40, 7812]\n",
|
||||
" [0, 3, 5, 16, 1008]\n",
|
||||
" [0, 3, 8, 21, 2080]\n",
|
||||
" [0, 3, 16, 33, 6440]\n",
|
||||
" [0, 4, 6, 20, 1980]\n",
|
||||
" [0, 4, 12, 30, 5852]\n",
|
||||
" [0, 5, 7, 24, 3432]\n",
|
||||
" [0, 6, 8, 28, 5460]\n",
|
||||
" [0, 7, 9, 32, 8160]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/crypta.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/crypta.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/crypta.ecl\n",
|
||||
" * SICStus : http://hakank.org/sicstus/crypta.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def decreasing(solver, x):\n",
|
||||
" for i in range(len(x) - 1):\n",
|
||||
" solver.Add(x[i] <= x[i + 1])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Curious set of integers\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 5\n",
|
||||
"max_val = 10000\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(0, max_val, \"x[%i]\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"decreasing(solver, x)\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if i != j:\n",
|
||||
" p = solver.IntVar(0, max_val, \"p[%i,%i]\" % (i, j))\n",
|
||||
" solver.Add(p * p - 1 == (x[i] * x[j]))\n",
|
||||
"\n",
|
||||
"# This is the original problem:\n",
|
||||
"# Which is the fifth number?\n",
|
||||
"v = [1, 3, 8, 120]\n",
|
||||
"b = [solver.IsMemberVar(x[i], v) for i in range(n)]\n",
|
||||
"solver.Add(solver.Sum(b) == 4)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"x:\", [int(x[i].Value()) for i in range(n)])\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
199
examples/notebook/contrib/debruijn_binary.ipynb
Normal file
199
examples/notebook/contrib/debruijn_binary.ipynb
Normal file
@@ -0,0 +1,199 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" de Bruijn sequences in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Implementation of de Bruijn sequences in Minizinc, both 'classical' and\n",
|
||||
" 'arbitrary'.\n",
|
||||
" The 'arbitrary' version is when the length of the sequence (m here) is <\n",
|
||||
" base**n.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the the web based programs:\n",
|
||||
" http://www.hakank.org/comb/debruijn.cgi\n",
|
||||
" http://www.hakank.org/comb/debruijn_arb.cgi\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/debruijn.eprime\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/debruijn_binary.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/debruijn.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/debruijn_binary.zinc\n",
|
||||
" * Choco: http://hakank.org/choco/DeBruijn.java\n",
|
||||
" * Comet: http://hakank.org/comet/debruijn.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/debruijn.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/debruijn.cpp\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/debruijn_binary.rb\n",
|
||||
" * JaCoP: http://hakank.org/JaCoP/DeBruijn.java\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"# converts a number (s) <-> an array of numbers (t) in the specific base.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def toNum(solver, t, s, base):\n",
|
||||
" tlen = len(t)\n",
|
||||
" solver.Add(\n",
|
||||
" s == solver.Sum([(base**(tlen - i - 1)) * t[i] for i in range(tlen)]))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"de Bruijn sequences\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"# base = 2 # the base to use, i.e. the alphabet 0..n-1\n",
|
||||
"# n = 3 # number of bits to use (n = 4 -> 0..base^n-1 = 0..2^4 -1, i.e. 0..15)\n",
|
||||
"# m = base**n # the length of the sequence. For \"arbitrary\" de Bruijn\n",
|
||||
"# sequences\n",
|
||||
"\n",
|
||||
"# base = 4\n",
|
||||
"# n = 4\n",
|
||||
"# m = base**n\n",
|
||||
"\n",
|
||||
"# harder problem\n",
|
||||
"#base = 13\n",
|
||||
"#n = 4\n",
|
||||
"#m = 52\n",
|
||||
"\n",
|
||||
"# for n = 4 with different value of base\n",
|
||||
"# base = 2 0.030 seconds 16 failures\n",
|
||||
"# base = 3 0.041 108\n",
|
||||
"# base = 4 0.070 384\n",
|
||||
"# base = 5 0.231 1000\n",
|
||||
"# base = 6 0.736 2160\n",
|
||||
"# base = 7 2.2 seconds 4116\n",
|
||||
"# base = 8 6 seconds 7168\n",
|
||||
"# base = 9 16 seconds 11664\n",
|
||||
"# base = 10 42 seconds 18000\n",
|
||||
"# base = 6\n",
|
||||
"# n = 4\n",
|
||||
"# m = base**n\n",
|
||||
"\n",
|
||||
"# if True then ensure that the number of occurrences of 0..base-1 is\n",
|
||||
"# the same (and if m mod base = 0)\n",
|
||||
"check_same_gcc = True\n",
|
||||
"\n",
|
||||
"print(\"base: %i n: %i m: %i\" % (base, n, m))\n",
|
||||
"if check_same_gcc:\n",
|
||||
" print(\"Checks gcc\")\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = [solver.IntVar(0, (base**n) - 1, \"x%i\" % i) for i in range(m)]\n",
|
||||
"binary = {}\n",
|
||||
"for i in range(m):\n",
|
||||
" for j in range(n):\n",
|
||||
" binary[(i, j)] = solver.IntVar(0, base - 1, \"x_%i_%i\" % (i, j))\n",
|
||||
"\n",
|
||||
"bin_code = [solver.IntVar(0, base - 1, \"bin_code%i\" % i) for i in range(m)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"#solver.Add(solver.AllDifferent([x[i] for i in range(m)]))\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"\n",
|
||||
"# converts x <-> binary\n",
|
||||
"for i in range(m):\n",
|
||||
" t = [solver.IntVar(0, base - 1, \"t_%i\" % j) for j in range(n)]\n",
|
||||
" toNum(solver, t, x[i], base)\n",
|
||||
" for j in range(n):\n",
|
||||
" solver.Add(binary[(i, j)] == t[j])\n",
|
||||
"\n",
|
||||
"# the de Bruijn condition\n",
|
||||
"# the first elements in binary[i] is the same as the last\n",
|
||||
"# elements in binary[i-i]\n",
|
||||
"for i in range(1, m - 1):\n",
|
||||
" for j in range(1, n - 1):\n",
|
||||
" solver.Add(binary[(i - 1, j)] == binary[(i, j - 1)])\n",
|
||||
"\n",
|
||||
"# ... and around the corner\n",
|
||||
"for j in range(1, n):\n",
|
||||
" solver.Add(binary[(m - 1, j)] == binary[(0, j - 1)])\n",
|
||||
"\n",
|
||||
"# converts binary -> bin_code\n",
|
||||
"for i in range(m):\n",
|
||||
" solver.Add(bin_code[i] == binary[(i, 0)])\n",
|
||||
"\n",
|
||||
"# extra: ensure that all the numbers in the de Bruijn sequence\n",
|
||||
"# (bin_code) has the same occurrences (if check_same_gcc is True\n",
|
||||
"# and mathematically possible)\n",
|
||||
"gcc = [solver.IntVar(0, m, \"gcc%i\" % i) for i in range(base)]\n",
|
||||
"solver.Add(solver.Distribute(bin_code, list(range(base)), gcc))\n",
|
||||
"if check_same_gcc and m % base == 0:\n",
|
||||
" for i in range(1, base):\n",
|
||||
" solver.Add(gcc[i] == gcc[i - 1])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([x[i] for i in range(m)])\n",
|
||||
"solution.Add([bin_code[i] for i in range(m)])\n",
|
||||
"# solution.Add([binary[(i,j)] for i in range(m) for j in range(n)])\n",
|
||||
"solution.Add([gcc[i] for i in range(base)])\n",
|
||||
"\n",
|
||||
"db = solver.Phase([x[i] for i in range(m)] + [bin_code[i] for i in range(m)],\n",
|
||||
" solver.CHOOSE_MIN_SIZE_LOWEST_MAX, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"\\nSolution %i\" % num_solutions)\n",
|
||||
" print(\"x:\", [int(x[i].Value()) for i in range(m)])\n",
|
||||
" print(\"gcc:\", [int(gcc[i].Value()) for i in range(base)])\n",
|
||||
" print(\"de Bruijn sequence:\", [int(bin_code[i].Value()) for i in range(m)])\n",
|
||||
" # for i in range(m):\n",
|
||||
" # for j in range(n):\n",
|
||||
" # print binary[(i,j)].Value(),\n",
|
||||
" # print\n",
|
||||
" # print\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"if num_solutions == 0:\n",
|
||||
" print(\"No solution found\")\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"base = 2\n",
|
||||
"n = 3\n",
|
||||
"m = base**n\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
112
examples/notebook/contrib/diet1.ipynb
Normal file
112
examples/notebook/contrib/diet1.ipynb
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Simple diet problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Standard Operations Research example in Minizinc\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Minimize the cost for the products:\n",
|
||||
" Type of Calories Chocolate Sugar Fat\n",
|
||||
" Food (ounces) (ounces) (ounces)\n",
|
||||
" Chocolate Cake (1 slice) 400 3 2 2\n",
|
||||
" Chocolate ice cream (1 scoop) 200 2 2 4\n",
|
||||
" Cola (1 bottle) 150 0 4 1\n",
|
||||
" Pineapple cheesecake (1 piece) 500 0 4 5\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/diet1.eprime\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/diet1.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/diet1.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/diet1.zinc\n",
|
||||
" * Choco: http://hakank.org/choco/Diet.java\n",
|
||||
" * Comet: http://hakank.org/comet/diet.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/diet.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/diet.cpp\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/diet.rb\n",
|
||||
" * JaCoP: http://hakank.org/JaCoP/Diet.java\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"price = [50, 20, 30, 80] # in cents\n",
|
||||
"limits = [500, 6, 10, 8] # requirements for each nutrition type\n",
|
||||
"\n",
|
||||
"# nutritions for each product\n",
|
||||
"calories = [400, 200, 150, 500]\n",
|
||||
"chocolate = [3, 2, 0, 0]\n",
|
||||
"sugar = [2, 2, 4, 4]\n",
|
||||
"fat = [2, 4, 1, 5]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [model.NewIntVar(0, 100, \"x%d\" % i) for i in range(n)]\n",
|
||||
"cost = model.NewIntVar(0, 10000, \"cost\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"model.Add(sum(x[i] * calories[i] for i in range(n)) >= limits[0])\n",
|
||||
"model.Add(sum(x[i] * chocolate[i] for i in range(n)) >= limits[1])\n",
|
||||
"model.Add(sum(x[i] * sugar[i] for i in range(n)) >= limits[2])\n",
|
||||
"model.Add(sum(x[i] * fat[i] for i in range(n)) >= limits[3])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"model.Minimize(cost)\n",
|
||||
"\n",
|
||||
"# Solve model.\n",
|
||||
"solver = cp_model.CpSolver()\n",
|
||||
"status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
"# Output solution.\n",
|
||||
"if status == cp_model.OPTIMAL:\n",
|
||||
" print(\"cost:\", solver.ObjectiveValue())\n",
|
||||
" print([(\"abcdefghij\" [i], solver.Value(x[i])) for i in range(n)])\n",
|
||||
" print()\n",
|
||||
" print(' - status : %s' % solver.StatusName(status))\n",
|
||||
" print(' - conflicts : %i' % solver.NumConflicts())\n",
|
||||
" print(' - branches : %i' % solver.NumBranches())\n",
|
||||
" print(' - wall time : %f ms' % solver.WallTime())\n",
|
||||
" print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
122
examples/notebook/contrib/diet1_b.ipynb
Normal file
122
examples/notebook/contrib/diet1_b.ipynb
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Simple diet problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Standard Operations Research example in Minizinc\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Minimize the cost for the products:\n",
|
||||
" Type of Calories Chocolate Sugar Fat\n",
|
||||
" Food (ounces) (ounces) (ounces)\n",
|
||||
" Chocolate Cake (1 slice) 400 3 2 2\n",
|
||||
" Chocolate ice cream (1 scoop) 200 2 2 4\n",
|
||||
" Cola (1 bottle) 150 0 4 1\n",
|
||||
" Pineapple cheesecake (1 piece) 500 0 4 5\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/diet1.eprime\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/diet1.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/diet1.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/diet1.zinc\n",
|
||||
" * Choco: http://hakank.org/choco/Diet.java\n",
|
||||
" * Comet: http://hakank.org/comet/diet.co\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/diet.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/diet.cpp\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/diet.rb\n",
|
||||
" * JaCoP: http://hakank.org/JaCoP/Diet.java\n",
|
||||
"\n",
|
||||
" This version use ScalProd() instead of Sum().\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Diet\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"price = [50, 20, 30, 80] # in cents\n",
|
||||
"limits = [500, 6, 10, 8] # requirements for each nutrition type\n",
|
||||
"\n",
|
||||
"# nutritions for each product\n",
|
||||
"calories = [400, 200, 150, 500]\n",
|
||||
"chocolate = [3, 2, 0, 0]\n",
|
||||
"sugar = [2, 2, 4, 4]\n",
|
||||
"fat = [2, 4, 1, 5]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(0, 100, \"x%d\" % i) for i in range(n)]\n",
|
||||
"cost = solver.IntVar(0, 10000, \"cost\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.ScalProd(x, calories) >= limits[0])\n",
|
||||
"solver.Add(solver.ScalProd(x, chocolate) >= limits[1])\n",
|
||||
"solver.Add(solver.ScalProd(x, sugar) >= limits[2])\n",
|
||||
"solver.Add(solver.ScalProd(x, fat) >= limits[3])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(cost, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.AddObjective(cost)\n",
|
||||
"solution.Add(x)\n",
|
||||
"\n",
|
||||
"# last solution since it's a minimization problem\n",
|
||||
"collector = solver.LastSolutionCollector(solution)\n",
|
||||
"search_log = solver.SearchLog(100, cost)\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase(x + [cost], solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE),\n",
|
||||
" [objective, search_log, collector])\n",
|
||||
"\n",
|
||||
"# get the first (and only) solution\n",
|
||||
"print(\"cost:\", collector.ObjectiveValue(0))\n",
|
||||
"print([(\"abcdefghij\" [i], collector.Value(0, x[i])) for i in range(n)])\n",
|
||||
"print()\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
113
examples/notebook/contrib/diet1_mip.ipynb
Normal file
113
examples/notebook/contrib/diet1_mip.ipynb
Normal file
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Simple diet problem using MIP in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Standard Operations Research example.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Minimize the cost for the products:\n",
|
||||
" Type of Calories Chocolate Sugar Fat\n",
|
||||
" Food (ounces) (ounces) (ounces)\n",
|
||||
" Chocolate Cake (1 slice) 400 3 2 2\n",
|
||||
" Chocolate ice cream (1 scoop) 200 2 2 4\n",
|
||||
" Cola (1 bottle) 150 0 4 1\n",
|
||||
" Pineapple cheesecake (1 piece) 500 0 4 5\n",
|
||||
"\n",
|
||||
" Compare with the CP model:\n",
|
||||
" http://www.hakank.org/google_or_tools/diet1.py\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" # using GLPK\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"price = [50, 20, 30, 80] # in cents\n",
|
||||
"limits = [500, 6, 10, 8] # requirements for each nutrition type\n",
|
||||
"\n",
|
||||
"# nutritions for each product\n",
|
||||
"calories = [400, 200, 150, 500]\n",
|
||||
"chocolate = [3, 2, 0, 0]\n",
|
||||
"sugar = [2, 2, 4, 4]\n",
|
||||
"fat = [2, 4, 1, 5]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(0, 100, 'x%d' % i) for i in range(n)]\n",
|
||||
"cost = solver.Sum([x[i] * price[i] for i in range(n)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.Sum([x[i] * calories[i] for i in range(n)]) >= limits[0])\n",
|
||||
"solver.Add(solver.Sum([x[i] * chocolate[i] for i in range(n)]) >= limits[1])\n",
|
||||
"solver.Add(solver.Sum([x[i] * sugar[i] for i in range(n)]) >= limits[2])\n",
|
||||
"solver.Add(solver.Sum([x[i] * fat[i] for i in range(n)]) >= limits[3])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(cost)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print('Cost:', solver.Objective().Value())\n",
|
||||
"print([int(x[i].SolutionValue()) for i in range(n)])\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('WallTime:', solver.WallTime())\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
170
examples/notebook/contrib/discrete_tomography.ipynb
Normal file
170
examples/notebook/contrib/discrete_tomography.ipynb
Normal file
@@ -0,0 +1,170 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Discrete tomography in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Problem from http://eclipse.crosscoreop.com/examples/tomo.ecl.txt\n",
|
||||
" '''\n",
|
||||
" This is a little 'tomography' problem, taken from an old issue\n",
|
||||
" of Scientific American.\n",
|
||||
"\n",
|
||||
" A matrix which contains zeroes and ones gets \"x-rayed\" vertically and\n",
|
||||
" horizontally, giving the total number of ones in each row and column.\n",
|
||||
" The problem is to reconstruct the contents of the matrix from this\n",
|
||||
" information. Sample run:\n",
|
||||
"\n",
|
||||
" ?- go.\n",
|
||||
" 0 0 7 1 6 3 4 5 2 7 0 0\n",
|
||||
" 0\n",
|
||||
" 0\n",
|
||||
" 8 * * * * * * * *\n",
|
||||
" 2 * *\n",
|
||||
" 6 * * * * * *\n",
|
||||
" 4 * * * *\n",
|
||||
" 5 * * * * *\n",
|
||||
" 3 * * *\n",
|
||||
" 7 * * * * * * *\n",
|
||||
" 0\n",
|
||||
" 0\n",
|
||||
"\n",
|
||||
" Eclipse solution by Joachim Schimpf, IC-Parc\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet: http://www.hakank.org/comet/discrete_tomography.co\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/discrete_tomography.cpp\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/tomography.mzn\n",
|
||||
" * Tailor/Essence': http://www.hakank.org/tailor/tomography.eprime\n",
|
||||
" * SICStus: http://hakank.org/sicstus/discrete_tomography.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"if row_sums == \"\":\n",
|
||||
" print(\"Using default problem instance\")\n",
|
||||
" row_sums = [0, 0, 8, 2, 6, 4, 5, 3, 7, 0, 0]\n",
|
||||
" col_sums = [0, 0, 7, 1, 6, 3, 4, 5, 2, 7, 0, 0]\n",
|
||||
"\n",
|
||||
"r = len(row_sums)\n",
|
||||
"c = len(col_sums)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"x = []\n",
|
||||
"for i in range(r):\n",
|
||||
" t = []\n",
|
||||
" for j in range(c):\n",
|
||||
" t.append(solver.IntVar(0, 1, \"x[%i,%i]\" % (i, j)))\n",
|
||||
" x.append(t)\n",
|
||||
"x_flat = [x[i][j] for i in range(r) for j in range(c)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"[\n",
|
||||
" solver.Add(solver.Sum([x[i][j]\n",
|
||||
" for j in range(c)]) == row_sums[i])\n",
|
||||
" for i in range(r)\n",
|
||||
"]\n",
|
||||
"[\n",
|
||||
" solver.Add(solver.Sum([x[i][j]\n",
|
||||
" for i in range(r)]) == col_sums[j])\n",
|
||||
" for j in range(c)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x_flat)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print_solution(x, r, c, row_sums, col_sums)\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Print solution\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"def print_solution(x, rows, cols, row_sums, col_sums):\n",
|
||||
" print(\" \", end=\" \")\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(col_sums[j], end=\" \")\n",
|
||||
" print()\n",
|
||||
" for i in range(rows):\n",
|
||||
" print(row_sums[i], end=\" \")\n",
|
||||
" for j in range(cols):\n",
|
||||
" if x[i][j].Value() == 1:\n",
|
||||
" print(\"#\", end=\" \")\n",
|
||||
" else:\n",
|
||||
" print(\".\", end=\" \")\n",
|
||||
" print(\"\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Read a problem instance from a file\n",
|
||||
"#\n",
|
||||
"def read_problem(file):\n",
|
||||
" f = open(file, \"r\")\n",
|
||||
" row_sums = f.readline()\n",
|
||||
" col_sums = f.readline()\n",
|
||||
" row_sums = [int(r) for r in (row_sums.rstrip()).split(\",\")]\n",
|
||||
" col_sums = [int(c) for c in (col_sums.rstrip()).split(\",\")]\n",
|
||||
"\n",
|
||||
" return [row_sums, col_sums]\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
179
examples/notebook/contrib/divisible_by_9_through_1.ipynb
Normal file
179
examples/notebook/contrib/divisible_by_9_through_1.ipynb
Normal file
@@ -0,0 +1,179 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Divisible by 9 through 1 puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://msdn.microsoft.com/en-us/vcsharp/ee957404.aspx\n",
|
||||
" ' Solving Combinatory Problems with LINQ'\n",
|
||||
" '''\n",
|
||||
" Find a number consisting of 9 digits in which each of the digits\n",
|
||||
" from 1 to 9 appears only once. This number must also satisfy these\n",
|
||||
" divisibility requirements:\n",
|
||||
"\n",
|
||||
" 1. The number should be divisible by 9.\n",
|
||||
" 2. If the rightmost digit is removed, the remaining number should\n",
|
||||
" be divisible by 8.\n",
|
||||
" 3. If the rightmost digit of the new number is removed, the remaining\n",
|
||||
" number should be divisible by 7.\n",
|
||||
" 4. And so on, until there's only one digit (which will necessarily\n",
|
||||
" be divisible by 1).\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Also, see\n",
|
||||
" 'Intel Parallel Studio: Great for Serial Code Too (Episode 1)'\n",
|
||||
" http://software.intel.com/en-us/blogs/2009/12/07/intel-parallel-studio-great-for-serial-code-too-episode-1/\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model is however generalized to handle any base, for reasonable limits.\n",
|
||||
" The 'reasonable limit' for this model is that base must be between 2..16.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/divisible_by_9_through_1.mzn\n",
|
||||
" * Comet : http://www.hakank.org/comet/divisible_by_9_through_1.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/divisible_by_9_through_1.ecl\n",
|
||||
" * Gecode : http://www.hakank.org/gecode/divisible_by_9_through_1.cpp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Decomposition of modulo constraint\n",
|
||||
"#\n",
|
||||
"# This implementation is based on the ECLiPSe version\n",
|
||||
"# mentioned in\n",
|
||||
"# - A Modulo propagator for ECLiPSE'\n",
|
||||
"# http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html\n",
|
||||
"# The ECLiPSe source code:\n",
|
||||
"# http://www.hakank.org/eclipse/modulo_propagator.ecl\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def my_mod(solver, x, y, r):\n",
|
||||
"\n",
|
||||
" if not isinstance(y, int):\n",
|
||||
" solver.Add(y != 0)\n",
|
||||
"\n",
|
||||
" lbx = x.Min()\n",
|
||||
" ubx = x.Max()\n",
|
||||
" ubx_neg = -ubx\n",
|
||||
" lbx_neg = -lbx\n",
|
||||
" min_x = min(lbx, ubx_neg)\n",
|
||||
" max_x = max(ubx, lbx_neg)\n",
|
||||
"\n",
|
||||
" d = solver.IntVar(max(0, min_x), max_x, \"d\")\n",
|
||||
"\n",
|
||||
" if not isinstance(r, int):\n",
|
||||
" solver.Add(r >= 0)\n",
|
||||
" solver.Add(x * r >= 0)\n",
|
||||
"\n",
|
||||
" if not isinstance(r, int) and not isinstance(r, int):\n",
|
||||
" solver.Add(-abs(y) < r)\n",
|
||||
" solver.Add(r < abs(y))\n",
|
||||
"\n",
|
||||
" solver.Add(min_x <= d)\n",
|
||||
" solver.Add(d <= max_x)\n",
|
||||
" solver.Add(x == y * d + r)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# converts a number (s) <-> an array of integers (t) in the specific base.\n",
|
||||
"#\n",
|
||||
"def toNum(solver, t, s, base):\n",
|
||||
" tlen = len(t)\n",
|
||||
" solver.Add(\n",
|
||||
" s == solver.Sum([(base**(tlen - i - 1)) * t[i] for i in range(tlen)]))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Divisible by 9 through 1\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"m = base**(base - 1) - 1\n",
|
||||
"n = base - 1\n",
|
||||
"\n",
|
||||
"digits_str = \"_0123456789ABCDEFGH\"\n",
|
||||
"\n",
|
||||
"print(\"base:\", base)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"\n",
|
||||
"# the digits\n",
|
||||
"x = [solver.IntVar(1, base - 1, \"x[%i]\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"# the numbers, t[0] contains the answer\n",
|
||||
"t = [solver.IntVar(0, m, \"t[%i]\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"\n",
|
||||
"for i in range(n):\n",
|
||||
" mm = base - i - 1\n",
|
||||
" toNum(solver, [x[j] for j in range(mm)], t[i], base)\n",
|
||||
" my_mod(solver, t[i], mm, 0)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(t)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"x: \", [x[i].Value() for i in range(n)])\n",
|
||||
" print(\"t: \", [t[i].Value() for i in range(n)])\n",
|
||||
" print(\"number base 10: %i base %i: %s\" % (t[0].Value(), base, \"\".join(\n",
|
||||
" [digits_str[x[i].Value() + 1] for i in range(n)])))\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"base = 10\n",
|
||||
"default_base = 10\n",
|
||||
"max_base = 16\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
57
examples/notebook/contrib/dudeney.ipynb
Normal file
57
examples/notebook/contrib/dudeney.ipynb
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Pierre Schaus (pschaus@gmail.com)\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",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def dudeney(n):\n",
|
||||
" solver = pywrapcp.Solver('Dudeney')\n",
|
||||
" x = [solver.IntVar(list(range(10)), 'x' + str(i)) for i in range(n)]\n",
|
||||
" nb = solver.IntVar(list(range(3, 10**n)), 'nb')\n",
|
||||
" s = solver.IntVar(list(range(1, 9 * n + 1)), 's')\n",
|
||||
"\n",
|
||||
" solver.Add(nb == s * s * s)\n",
|
||||
" solver.Add(sum([10**(n - i - 1) * x[i] for i in range(n)]) == nb)\n",
|
||||
" solver.Add(sum([x[i] for i in range(n)]) == s)\n",
|
||||
"\n",
|
||||
" solution = solver.Assignment()\n",
|
||||
" solution.Add(nb)\n",
|
||||
" collector = solver.AllSolutionCollector(solution)\n",
|
||||
"\n",
|
||||
" solver.Solve(\n",
|
||||
" solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n",
|
||||
" [collector])\n",
|
||||
"\n",
|
||||
" for i in range(collector.SolutionCount()):\n",
|
||||
" nbsol = collector.Value(i, nb)\n",
|
||||
" print(nbsol)\n",
|
||||
"\n",
|
||||
" print('#fails:', solver.Failures())\n",
|
||||
" print('time:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
210
examples/notebook/contrib/einav_puzzle.ipynb
Normal file
210
examples/notebook/contrib/einav_puzzle.ipynb
Normal file
@@ -0,0 +1,210 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" A programming puzzle from Einav in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From\n",
|
||||
" 'A programming puzzle from Einav'\n",
|
||||
" http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/\n",
|
||||
" '''\n",
|
||||
" My friend Einav gave me this programming puzzle to work on. Given\n",
|
||||
" this array of positive and negative numbers:\n",
|
||||
" 33 30 -10 -6 18 7 -11 -23 6\n",
|
||||
" ...\n",
|
||||
" -25 4 16 30 33 -23 -4 4 -23\n",
|
||||
"\n",
|
||||
" You can flip the sign of entire rows and columns, as many of them\n",
|
||||
" as you like. The goal is to make all the rows and columns sum to positive\n",
|
||||
" numbers (or zero), and then to find the solution (there are more than one)\n",
|
||||
" that has the smallest overall sum. So for example, for this array:\n",
|
||||
" 33 30 -10\n",
|
||||
" -16 19 9\n",
|
||||
" -17 -12 -14\n",
|
||||
" You could flip the sign for the bottom row to get this array:\n",
|
||||
" 33 30 -10\n",
|
||||
" -16 19 9\n",
|
||||
" 17 12 14\n",
|
||||
" Now all the rows and columns have positive sums, and the overall total is\n",
|
||||
" 108.\n",
|
||||
" But you could instead flip the second and third columns, and the second\n",
|
||||
" row, to get this array:\n",
|
||||
" 33 -30 10\n",
|
||||
" 16 19 9\n",
|
||||
" -17 12 14\n",
|
||||
" All the rows and columns still total positive, and the overall sum is just\n",
|
||||
" 66. So this solution is better (I don't know if it's the best)\n",
|
||||
" A pure brute force solution would have to try over 30 billion solutions.\n",
|
||||
" I wrote code to solve this in J. I'll post that separately.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc http://www.hakank.org/minizinc/einav_puzzle.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/einav_puzzle.pl\n",
|
||||
"\n",
|
||||
" Note:\n",
|
||||
" einav_puzzle2.py is Laurent Perron version, which don't use as many\n",
|
||||
" decision variables as this version.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Einav puzzle')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# small problem\n",
|
||||
"# rows = 3;\n",
|
||||
"# cols = 3;\n",
|
||||
"# data = [\n",
|
||||
"# [ 33, 30, -10],\n",
|
||||
"# [-16, 19, 9],\n",
|
||||
"# [-17, -12, -14]\n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"# Full problem\n",
|
||||
"rows = 27\n",
|
||||
"cols = 9\n",
|
||||
"data = [[33, 30, 10, -6, 18, -7, -11, 23, -6],\n",
|
||||
" [16, -19, 9, -26, -8, -19, -8, -21, -14],\n",
|
||||
" [17, 12, -14, 31, -30, 13, -13, 19, 16],\n",
|
||||
" [-6, -11, 1, 17, -12, -4, -7, 14, -21],\n",
|
||||
" [18, -31, 34, -22, 17, -19, 20, 24, 6],\n",
|
||||
" [33, -18, 17, -15, 31, -5, 3, 27, -3],\n",
|
||||
" [-18, -20, -18, 31, 6, 4, -2, -12, 24],\n",
|
||||
" [27, 14, 4, -29, -3, 5, -29, 8, -12],\n",
|
||||
" [-15, -7, -23, 23, -9, -8, 6, 8, -12],\n",
|
||||
" [33, -23, -19, -4, -8, -7, 11, -12, 31],\n",
|
||||
" [-20, 19, -15, -30, 11, 32, 7, 14, -5],\n",
|
||||
" [-23, 18, -32, -2, -31, -7, 8, 24, 16],\n",
|
||||
" [32, -4, -10, -14, -6, -1, 0, 23, 23],\n",
|
||||
" [25, 0, -23, 22, 12, 28, -27, 15, 4],\n",
|
||||
" [-30, -13, -16, -3, -3, -32, -3, 27, -31],\n",
|
||||
" [22, 1, 26, 4, -2, -13, 26, 17, 14],\n",
|
||||
" [-9, -18, 3, -20, -27, -32, -11, 27, 13],\n",
|
||||
" [-17, 33, -7, 19, -32, 13, -31, -2, -24],\n",
|
||||
" [-31, 27, -31, -29, 15, 2, 29, -15, 33],\n",
|
||||
" [-18, -23, 15, 28, 0, 30, -4, 12, -32],\n",
|
||||
" [-3, 34, 27, -25, -18, 26, 1, 34, 26],\n",
|
||||
" [-21, -31, -10, -13, -30, -17, -12, -26, 31],\n",
|
||||
" [23, -31, -19, 21, -17, -10, 2, -23, 23],\n",
|
||||
" [-3, 6, 0, -3, -32, 0, -10, -25, 14],\n",
|
||||
" [-19, 9, 14, -27, 20, 15, -5, -27, 18],\n",
|
||||
" [11, -6, 24, 7, -17, 26, 20, -31, -25],\n",
|
||||
" [-25, 4, -16, 30, 33, 23, -4, -4, 23]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" x[i, j] = solver.IntVar(-100, 100, 'x[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"row_sums = [solver.IntVar(0, 300, 'row_sums(%i)' % i) for i in range(rows)]\n",
|
||||
"col_sums = [solver.IntVar(0, 300, 'col_sums(%i)' % j) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"row_signs = [solver.IntVar([-1, 1], 'row_signs(%i)' % i) for i in range(rows)]\n",
|
||||
"col_signs = [solver.IntVar([-1, 1], 'col_signs(%i)' % j) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"# total sum: to be minimized\n",
|
||||
"total_sum = solver.IntVar(0, 1000, 'total_sum')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" solver.Add(x[i, j] == data[i][j] * row_signs[i] * col_signs[j])\n",
|
||||
"\n",
|
||||
"total_sum_a = [\n",
|
||||
" data[i][j] * row_signs[i] * col_signs[j]\n",
|
||||
" for i in range(rows)\n",
|
||||
" for j in range(cols)\n",
|
||||
"]\n",
|
||||
"solver.Add(total_sum == solver.Sum(total_sum_a))\n",
|
||||
"\n",
|
||||
"# row sums\n",
|
||||
"for i in range(rows):\n",
|
||||
" s = [row_signs[i] * col_signs[j] * data[i][j] for j in range(cols)]\n",
|
||||
" solver.Add(row_sums[i] == solver.Sum(s))\n",
|
||||
"\n",
|
||||
"# column sums\n",
|
||||
"for j in range(cols):\n",
|
||||
" s = [row_signs[i] * col_signs[j] * data[i][j] for i in range(rows)]\n",
|
||||
" solver.Add(col_sums[j] == solver.Sum(s))\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(total_sum, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"# Note: The order of the variables makes a big difference.\n",
|
||||
"# If row_signs are before col_sign it is much slower.\n",
|
||||
"db = solver.Phase(col_signs + row_signs, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_MAX_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('total_sum:', total_sum.Value())\n",
|
||||
" print('row_sums:', [row_sums[i].Value() for i in range(rows)])\n",
|
||||
" print('col_sums:', [col_sums[j].Value() for j in range(cols)])\n",
|
||||
" print('row_signs:', [row_signs[i].Value() for i in range(rows)])\n",
|
||||
" print('col_signs:', [col_signs[j].Value() for j in range(cols)])\n",
|
||||
" print('x:')\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print('%3i' % x[i, j].Value(), end=' ')\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
204
examples/notebook/contrib/einav_puzzle2.ipynb
Normal file
204
examples/notebook/contrib/einav_puzzle2.ipynb
Normal file
@@ -0,0 +1,204 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" A programming puzzle from Einav in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From\n",
|
||||
" 'A programming puzzle from Einav'\n",
|
||||
" http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/\n",
|
||||
" '''\n",
|
||||
" My friend Einav gave me this programming puzzle to work on. Given\n",
|
||||
" this array of positive and negative numbers:\n",
|
||||
" 33 30 -10 -6 18 7 -11 -23 6\n",
|
||||
" ...\n",
|
||||
" -25 4 16 30 33 -23 -4 4 -23\n",
|
||||
"\n",
|
||||
" You can flip the sign of entire rows and columns, as many of them\n",
|
||||
" as you like. The goal is to make all the rows and columns sum to positive\n",
|
||||
" numbers (or zero), and then to find the solution (there are more than one)\n",
|
||||
" that has the smallest overall sum. So for example, for this array:\n",
|
||||
" 33 30 -10\n",
|
||||
" -16 19 9\n",
|
||||
" -17 -12 -14\n",
|
||||
" You could flip the sign for the bottom row to get this array:\n",
|
||||
" 33 30 -10\n",
|
||||
" -16 19 9\n",
|
||||
" 17 12 14\n",
|
||||
" Now all the rows and columns have positive sums, and the overall total is\n",
|
||||
" 108.\n",
|
||||
" But you could instead flip the second and third columns, and the second\n",
|
||||
" row, to get this array:\n",
|
||||
" 33 -30 10\n",
|
||||
" 16 19 9\n",
|
||||
" -17 12 14\n",
|
||||
" All the rows and columns still total positive, and the overall sum is just\n",
|
||||
" 66. So this solution is better (I don't know if it's the best)\n",
|
||||
" A pure brute force solution would have to try over 30 billion solutions.\n",
|
||||
" I wrote code to solve this in J. I'll post that separately.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc http://www.hakank.org/minizinc/einav_puzzle.mzn\n",
|
||||
" * SICStus: http://hakank.org/sicstus/einav_puzzle.pl\n",
|
||||
"\n",
|
||||
" Note:\n",
|
||||
" This is a Larent Perrons's variant of einav_puzzle.py.\n",
|
||||
" He removed some of the decision variables and made it more efficient.\n",
|
||||
" Thanks!\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Einav puzzle\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# small problem\n",
|
||||
"# rows = 3;\n",
|
||||
"# cols = 3;\n",
|
||||
"# data = [\n",
|
||||
"# [ 33, 30, -10],\n",
|
||||
"# [-16, 19, 9],\n",
|
||||
"# [-17, -12, -14]\n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"# Full problem\n",
|
||||
"rows = 27\n",
|
||||
"cols = 9\n",
|
||||
"data = [[33, 30, 10, -6, 18, -7, -11, 23, -6],\n",
|
||||
" [16, -19, 9, -26, -8, -19, -8, -21, -14],\n",
|
||||
" [17, 12, -14, 31, -30, 13, -13, 19, 16],\n",
|
||||
" [-6, -11, 1, 17, -12, -4, -7, 14, -21],\n",
|
||||
" [18, -31, 34, -22, 17, -19, 20, 24, 6],\n",
|
||||
" [33, -18, 17, -15, 31, -5, 3, 27, -3],\n",
|
||||
" [-18, -20, -18, 31, 6, 4, -2, -12, 24],\n",
|
||||
" [27, 14, 4, -29, -3, 5, -29, 8, -12],\n",
|
||||
" [-15, -7, -23, 23, -9, -8, 6, 8, -12],\n",
|
||||
" [33, -23, -19, -4, -8, -7, 11, -12, 31],\n",
|
||||
" [-20, 19, -15, -30, 11, 32, 7, 14, -5],\n",
|
||||
" [-23, 18, -32, -2, -31, -7, 8, 24, 16],\n",
|
||||
" [32, -4, -10, -14, -6, -1, 0, 23, 23],\n",
|
||||
" [25, 0, -23, 22, 12, 28, -27, 15, 4],\n",
|
||||
" [-30, -13, -16, -3, -3, -32, -3, 27, -31],\n",
|
||||
" [22, 1, 26, 4, -2, -13, 26, 17, 14],\n",
|
||||
" [-9, -18, 3, -20, -27, -32, -11, 27, 13],\n",
|
||||
" [-17, 33, -7, 19, -32, 13, -31, -2, -24],\n",
|
||||
" [-31, 27, -31, -29, 15, 2, 29, -15, 33],\n",
|
||||
" [-18, -23, 15, 28, 0, 30, -4, 12, -32],\n",
|
||||
" [-3, 34, 27, -25, -18, 26, 1, 34, 26],\n",
|
||||
" [-21, -31, -10, -13, -30, -17, -12, -26, 31],\n",
|
||||
" [23, -31, -19, 21, -17, -10, 2, -23, 23],\n",
|
||||
" [-3, 6, 0, -3, -32, 0, -10, -25, 14],\n",
|
||||
" [-19, 9, 14, -27, 20, 15, -5, -27, 18],\n",
|
||||
" [11, -6, 24, 7, -17, 26, 20, -31, -25],\n",
|
||||
" [-25, 4, -16, 30, 33, 23, -4, -4, 23]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" x[i, j] = solver.IntVar(-100, 100, \"x[%i,%i]\" % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"row_signs = [solver.IntVar([-1, 1], \"row_signs(%i)\" % i) for i in range(rows)]\n",
|
||||
"col_signs = [solver.IntVar([-1, 1], \"col_signs(%i)\" % j) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" solver.Add(x[i, j] == data[i][j] * row_signs[i] * col_signs[j])\n",
|
||||
"\n",
|
||||
"total_sum = solver.Sum([x[i, j] for i in range(rows) for j in range(cols)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Note: In einav_puzzle.py row_sums and col_sums are decision variables.\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# row sums\n",
|
||||
"row_sums = [\n",
|
||||
" solver.Sum([x[i, j] for j in range(cols)]).Var() for i in range(rows)\n",
|
||||
"]\n",
|
||||
"# >= 0\n",
|
||||
"for i in range(rows):\n",
|
||||
" row_sums[i].SetMin(0)\n",
|
||||
"\n",
|
||||
"# column sums\n",
|
||||
"col_sums = [\n",
|
||||
" solver.Sum([x[i, j] for i in range(rows)]).Var() for j in range(cols)\n",
|
||||
"]\n",
|
||||
"for j in range(cols):\n",
|
||||
" col_sums[j].SetMin(0)\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(total_sum, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(col_signs + row_signs, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_MAX_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"Sum =\", objective.Best())\n",
|
||||
" print(\"row_sums:\", [row_sums[i].Value() for i in range(rows)])\n",
|
||||
" print(\"col_sums:\", [col_sums[j].Value() for j in range(cols)])\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(\"%3i\" % x[i, j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
116
examples/notebook/contrib/eq10.ipynb
Normal file
116
examples/notebook/contrib/eq10.ipynb
Normal file
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Eq 10 in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Standard benchmark problem.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/eq10.mzn\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/eq10.ecl\n",
|
||||
" * SICStus: http://hakank.org/sicstus/eq10.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Eq 10\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 7\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"X = [solver.IntVar(0, 10, \"X(%i)\" % i) for i in range(n)]\n",
|
||||
"X1, X2, X3, X4, X5, X6, X7 = X\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(0 + 98527 * X1 + 34588 * X2 + 5872 * X3 + 59422 * X5 +\n",
|
||||
" 65159 * X7 == 1547604 + 30704 * X4 + 29649 * X6)\n",
|
||||
"\n",
|
||||
"solver.Add(0 + 98957 * X2 + 83634 * X3 + 69966 * X4 + 62038 * X5 +\n",
|
||||
" 37164 * X6 + 85413 * X7 == 1823553 + 93989 * X1)\n",
|
||||
"\n",
|
||||
"solver.Add(900032 + 10949 * X1 + 77761 * X2 + 67052 * X5 == 0 + 80197 * X3 +\n",
|
||||
" 61944 * X4 + 92964 * X6 + 44550 * X7)\n",
|
||||
"\n",
|
||||
"solver.Add(0 + 73947 * X1 + 84391 * X3 + 81310 * X5 == 1164380 + 96253 * X2 +\n",
|
||||
" 44247 * X4 + 70582 * X6 + 33054 * X7)\n",
|
||||
"\n",
|
||||
"solver.Add(0 + 13057 * X3 + 42253 * X4 + 77527 * X5 + 96552 * X7 == 1185471 +\n",
|
||||
" 60152 * X1 + 21103 * X2 + 97932 * X6)\n",
|
||||
"\n",
|
||||
"solver.Add(1394152 + 66920 * X1 + 55679 * X4 == 0 + 64234 * X2 + 65337 * X3 +\n",
|
||||
" 45581 * X5 + 67707 * X6 + 98038 * X7)\n",
|
||||
"\n",
|
||||
"solver.Add(0 + 68550 * X1 + 27886 * X2 + 31716 * X3 + 73597 * X4 +\n",
|
||||
" 38835 * X7 == 279091 + 88963 * X5 + 76391 * X6)\n",
|
||||
"\n",
|
||||
"solver.Add(0 + 76132 * X2 + 71860 * X3 + 22770 * X4 + 68211 * X5 +\n",
|
||||
" 78587 * X6 == 480923 + 48224 * X1 + 82817 * X7)\n",
|
||||
"\n",
|
||||
"solver.Add(519878 + 94198 * X2 + 87234 * X3 + 37498 * X4 == 0 + 71583 * X1 +\n",
|
||||
" 25728 * X5 + 25495 * X6 + 70023 * X7)\n",
|
||||
"\n",
|
||||
"solver.Add(361921 + 78693 * X1 + 38592 * X5 + 38478 * X6 == 0 + 94129 * X2 +\n",
|
||||
" 43188 * X3 + 82528 * X4 + 69025 * X7)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(X, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"X:\", [X[i].Value() for i in range(n)])\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
127
examples/notebook/contrib/eq20.ipynb
Normal file
127
examples/notebook/contrib/eq20.ipynb
Normal file
@@ -0,0 +1,127 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Eq 20 in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Standard benchmark problem.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Gecode/R: http://hakank.org/gecode_r/eq20.rb\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/eq20.ecl\n",
|
||||
" * SICStus: http://hakank.org/sicstus/eq20.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Eq 20\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 7\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"X = [solver.IntVar(0, 10, \"X(%i)\" % i) for i in range(n)]\n",
|
||||
"X0, X1, X2, X3, X4, X5, X6 = X\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(-76706 * X0 + 98205 * X1 + 23445 * X2 + 67921 * X3 + 24111 * X4 +\n",
|
||||
" -48614 * X5 + -41906 * X6 == 821228)\n",
|
||||
"solver.Add(87059 * X0 + -29101 * X1 + -5513 * X2 + -21219 * X3 + 22128 * X4 +\n",
|
||||
" 7276 * X5 + 57308 * X6 == 22167)\n",
|
||||
"solver.Add(-60113 * X0 + 29475 * X1 + 34421 * X2 + -76870 * X3 + 62646 * X4 +\n",
|
||||
" 29278 * X5 + -15212 * X6 == 251591)\n",
|
||||
"solver.Add(49149 * X0 + 52871 * X1 + -7132 * X2 + 56728 * X3 + -33576 * X4 +\n",
|
||||
" -49530 * X5 + -62089 * X6 == 146074)\n",
|
||||
"solver.Add(-10343 * X0 + 87758 * X1 + -11782 * X2 + 19346 * X3 + 70072 * X4 +\n",
|
||||
" -36991 * X5 + 44529 * X6 == 740061)\n",
|
||||
"solver.Add(85176 * X0 + -95332 * X1 + -1268 * X2 + 57898 * X3 + 15883 * X4 +\n",
|
||||
" 50547 * X5 + 83287 * X6 == 373854)\n",
|
||||
"solver.Add(-85698 * X0 + 29958 * X1 + 57308 * X2 + 48789 * X3 + -78219 * X4 +\n",
|
||||
" 4657 * X5 + 34539 * X6 == 249912)\n",
|
||||
"solver.Add(-67456 * X0 + 84750 * X1 + -51553 * X2 + 21239 * X3 + 81675 * X4 +\n",
|
||||
" -99395 * X5 + -4254 * X6 == 277271)\n",
|
||||
"solver.Add(94016 * X0 + -82071 * X1 + 35961 * X2 + 66597 * X3 + -30705 * X4 +\n",
|
||||
" -44404 * X5 + -38304 * X6 == 25334)\n",
|
||||
"solver.Add(-60301 * X0 + 31227 * X1 + 93951 * X2 + 73889 * X3 + 81526 * X4 +\n",
|
||||
" -72702 * X5 + 68026 * X6 == 1410723)\n",
|
||||
"solver.Add(-16835 * X0 + 47385 * X1 + 97715 * X2 + -12640 * X3 + 69028 * X4 +\n",
|
||||
" 76212 * X5 + -81102 * X6 == 1244857)\n",
|
||||
"solver.Add(-43277 * X0 + 43525 * X1 + 92298 * X2 + 58630 * X3 + 92590 * X4 +\n",
|
||||
" -9372 * X5 + -60227 * X6 == 1503588)\n",
|
||||
"solver.Add(-64919 * X0 + 80460 * X1 + 90840 * X2 + -59624 * X3 + -75542 * X4 +\n",
|
||||
" 25145 * X5 + -47935 * X6 == 18465)\n",
|
||||
"solver.Add(-45086 * X0 + 51830 * X1 + -4578 * X2 + 96120 * X3 + 21231 * X4 +\n",
|
||||
" 97919 * X5 + 65651 * X6 == 1198280)\n",
|
||||
"solver.Add(85268 * X0 + 54180 * X1 + -18810 * X2 + -48219 * X3 + 6013 * X4 +\n",
|
||||
" 78169 * X5 + -79785 * X6 == 90614)\n",
|
||||
"solver.Add(8874 * X0 + -58412 * X1 + 73947 * X2 + 17147 * X3 + 62335 * X4 +\n",
|
||||
" 16005 * X5 + 8632 * X6 == 752447)\n",
|
||||
"solver.Add(71202 * X0 + -11119 * X1 + 73017 * X2 + -38875 * X3 + -14413 * X4 +\n",
|
||||
" -29234 * X5 + 72370 * X6 == 129768)\n",
|
||||
"solver.Add(1671 * X0 + -34121 * X1 + 10763 * X2 + 80609 * X3 + 42532 * X4 +\n",
|
||||
" 93520 * X5 + -33488 * X6 == 915683)\n",
|
||||
"solver.Add(51637 * X0 + 67761 * X1 + 95951 * X2 + 3834 * X3 + -96722 * X4 +\n",
|
||||
" 59190 * X5 + 15280 * X6 == 533909)\n",
|
||||
"solver.Add(-16105 * X0 + 62397 * X1 + -6704 * X2 + 43340 * X3 + 95100 * X4 +\n",
|
||||
" -68610 * X5 + 58301 * X6 == 876370)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(X, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"X:\", [X[i].Value() for i in range(n)])\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
182
examples/notebook/contrib/fill_a_pix.ipynb
Normal file
182
examples/notebook/contrib/fill_a_pix.ipynb
Normal file
@@ -0,0 +1,182 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Fill-a-Pix problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From\n",
|
||||
" http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/basiclogic\n",
|
||||
" '''\n",
|
||||
" Each puzzle consists of a grid containing clues in various places. The\n",
|
||||
" object is to reveal a hidden picture by painting the squares around each\n",
|
||||
" clue so that the number of painted squares, including the square with\n",
|
||||
" the clue, matches the value of the clue.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules\n",
|
||||
" '''\n",
|
||||
" Fill-a-Pix is a Minesweeper-like puzzle based on a grid with a pixilated\n",
|
||||
" picture hidden inside. Using logic alone, the solver determines which\n",
|
||||
" squares are painted and which should remain empty until the hidden picture\n",
|
||||
" is completely exposed.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Fill-a-pix History:\n",
|
||||
" http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/history\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/fill_a_pix.mzn\n",
|
||||
" * SICStus Prolog: http://www.hakank.org/sicstus/fill_a_pix.pl\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/fill_a_pix.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/fill_a_pix.cpp\n",
|
||||
"\n",
|
||||
" And see the Minesweeper model:\n",
|
||||
" * http://www.hakank.org/google_or_tools/minesweeper.py\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"# Puzzle 1 from\n",
|
||||
"# http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules\n",
|
||||
"default_n = 10\n",
|
||||
"X = -1\n",
|
||||
"default_puzzle = [\n",
|
||||
" [X, X, X, X, X, X, X, X, 0, X], [X, 8, 8, X, 2, X, 0, X, X, X],\n",
|
||||
" [5, X, 8, X, X, X, X, X, X, X], [X, X, X, X, X, 2, X, X, X, 2],\n",
|
||||
" [1, X, X, X, 4, 5, 6, X, X, X], [X, 0, X, X, X, 7, 9, X, X, 6],\n",
|
||||
" [X, X, X, 6, X, X, 9, X, X, 6], [X, X, 6, 6, 8, 7, 8, 7, X, 5],\n",
|
||||
" [X, 4, X, 6, 6, 6, X, 6, X, 4], [X, X, X, X, X, X, 3, X, X, X]\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Fill-a-Pix')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# Set default problem\n",
|
||||
"if puzzle == '':\n",
|
||||
" puzzle = default_puzzle\n",
|
||||
" n = default_n\n",
|
||||
"else:\n",
|
||||
" print('n:', n)\n",
|
||||
"\n",
|
||||
"# for the neighbors of 'this' cell\n",
|
||||
"S = [-1, 0, 1]\n",
|
||||
"\n",
|
||||
"# print problem instance\n",
|
||||
"print('Problem:')\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if puzzle[i][j] == X:\n",
|
||||
" sys.stdout.write('.')\n",
|
||||
" else:\n",
|
||||
" sys.stdout.write(str(puzzle[i][j]))\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"pict = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" pict[(i, j)] = solver.IntVar(0, 1, 'pict %i %i' % (i, j))\n",
|
||||
"\n",
|
||||
"pict_flat = [pict[i, j] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if puzzle[i][j] > X:\n",
|
||||
" # this cell is the sum of all the surrounding cells\n",
|
||||
" solver.Add(puzzle[i][j] == solver.Sum([\n",
|
||||
" pict[i + a, j + b]\n",
|
||||
" for a in S\n",
|
||||
" for b in S\n",
|
||||
" if i + a >= 0 and j + b >= 0 and i + a < n and j + b < n\n",
|
||||
" ]))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(pict_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"print('Solution:')\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in range(n):\n",
|
||||
" row = [str(pict[i, j].Value()) for j in range(n)]\n",
|
||||
" for j in range(n):\n",
|
||||
" if row[j] == '0':\n",
|
||||
" row[j] = ' '\n",
|
||||
" else:\n",
|
||||
" row[j] = '#'\n",
|
||||
" print(''.join(row))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Read a problem instance from a file\n",
|
||||
"#def read_problem(file):\n",
|
||||
" f = open(file, 'r')\n",
|
||||
" n = int(f.readline())\n",
|
||||
" puzzle = []\n",
|
||||
" for i in range(n):\n",
|
||||
" x = f.readline()\n",
|
||||
" row = [0] * n\n",
|
||||
" for j in range(n):\n",
|
||||
" if x[j] == '.':\n",
|
||||
" tmp = -1\n",
|
||||
" else:\n",
|
||||
" tmp = int(x[j])\n",
|
||||
" row[j] = tmp\n",
|
||||
" puzzle.append(row)\n",
|
||||
" return [puzzle, n]\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
187
examples/notebook/contrib/furniture_moving.ipynb
Normal file
187
examples/notebook/contrib/furniture_moving.ipynb
Normal file
@@ -0,0 +1,187 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Moving furnitures (scheduling) problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Marriott & Stukey: 'Programming with constraints', page 112f\n",
|
||||
"\n",
|
||||
" The model implements an experimental decomposition of the\n",
|
||||
" global constraint cumulative.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * ECLiPSE: http://www.hakank.org/eclipse/furniture_moving.ecl\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/furniture_moving.mzn\n",
|
||||
" * Comet: http://www.hakank.org/comet/furniture_moving.co\n",
|
||||
" * Choco: http://www.hakank.org/choco/FurnitureMoving.java\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/furniture_moving.cpp\n",
|
||||
" * JaCoP: http://www.hakank.org/JaCoP/FurnitureMoving.java\n",
|
||||
" * SICStus: http://hakank.org/sicstus/furniture_moving.pl\n",
|
||||
" * Zinc: http://hakank.org/minizinc/furniture_moving.zinc\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Decompositon of cumulative.\n",
|
||||
"#\n",
|
||||
"# Inspired by the MiniZinc implementation:\n",
|
||||
"# http://www.g12.csse.unimelb.edu.au/wiki/doku.php?id=g12:zinc:lib:minizinc:std:cumulative.mzn&s[]=cumulative\n",
|
||||
"# The MiniZinc decomposition is discussed in the paper:\n",
|
||||
"# A. Schutt, T. Feydy, P.J. Stuckey, and M. G. Wallace.\n",
|
||||
"# 'Why cumulative decomposition is not as bad as it sounds.'\n",
|
||||
"# Download:\n",
|
||||
"# http://www.cs.mu.oz.au/%7Epjs/rcpsp/papers/cp09-cu.pdf\n",
|
||||
"# http://www.cs.mu.oz.au/%7Epjs/rcpsp/cumu_lazyfd.pdf\n",
|
||||
"#\n",
|
||||
"#\n",
|
||||
"# Parameters:\n",
|
||||
"#\n",
|
||||
"# s: start_times assumption: array of IntVar\n",
|
||||
"# d: durations assumption: array of int\n",
|
||||
"# r: resources assumption: array of int\n",
|
||||
"# b: resource limit assumption: IntVar or int\n",
|
||||
"#\n",
|
||||
"def my_cumulative(solver, s, d, r, b):\n",
|
||||
"\n",
|
||||
" # tasks = [i for i in range(len(s))]\n",
|
||||
" tasks = [i for i in range(len(s)) if r[i] > 0 and d[i] > 0]\n",
|
||||
" times_min = min([s[i].Min() for i in tasks])\n",
|
||||
" times_max = max([s[i].Max() + max(d) for i in tasks])\n",
|
||||
" for t in range(times_min, times_max + 1):\n",
|
||||
" bb = []\n",
|
||||
" for i in tasks:\n",
|
||||
" c1 = solver.IsLessOrEqualCstVar(s[i], t) # s[i] <= t\n",
|
||||
" c2 = solver.IsGreaterCstVar(s[i] + d[i], t) # t < s[i] + d[i]\n",
|
||||
" bb.append(c1 * c2 * r[i])\n",
|
||||
" solver.Add(solver.Sum(bb) <= b)\n",
|
||||
"\n",
|
||||
" # Somewhat experimental:\n",
|
||||
" # This constraint is needed to contrain the upper limit of b.\n",
|
||||
" if not isinstance(b, int):\n",
|
||||
" solver.Add(b <= sum(r))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Furniture moving\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"duration = [30, 10, 15, 15]\n",
|
||||
"demand = [3, 1, 3, 2]\n",
|
||||
"upper_limit = 160\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"start_times = [\n",
|
||||
" solver.IntVar(0, upper_limit, \"start_times[%i]\" % i) for i in range(n)\n",
|
||||
"]\n",
|
||||
"end_times = [\n",
|
||||
" solver.IntVar(0, upper_limit * 2, \"end_times[%i]\" % i) for i in range(n)\n",
|
||||
"]\n",
|
||||
"end_time = solver.IntVar(0, upper_limit * 2, \"end_time\")\n",
|
||||
"\n",
|
||||
"# number of needed resources, to be minimized\n",
|
||||
"num_resources = solver.IntVar(0, 10, \"num_resources\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(n):\n",
|
||||
" solver.Add(end_times[i] == start_times[i] + duration[i])\n",
|
||||
"\n",
|
||||
"solver.Add(end_time == solver.Max(end_times))\n",
|
||||
"\n",
|
||||
"my_cumulative(solver, start_times, duration, demand, num_resources)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Some extra constraints to play with\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# all tasks must end within an hour\n",
|
||||
"# solver.Add(end_time <= 60)\n",
|
||||
"\n",
|
||||
"# All tasks should start at time 0\n",
|
||||
"# for i in range(n):\n",
|
||||
"# solver.Add(start_times[i] == 0)\n",
|
||||
"\n",
|
||||
"# limitation of the number of people\n",
|
||||
"# solver.Add(num_resources <= 3)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# objective\n",
|
||||
"#\n",
|
||||
"# objective = solver.Minimize(end_time, 1)\n",
|
||||
"objective = solver.Minimize(num_resources, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(start_times)\n",
|
||||
"solution.Add(end_times)\n",
|
||||
"solution.Add(end_time)\n",
|
||||
"solution.Add(num_resources)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(start_times, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# result\n",
|
||||
"#\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"num_resources:\", num_resources.Value())\n",
|
||||
" print(\"start_times :\", [start_times[i].Value() for i in range(n)])\n",
|
||||
" print(\"duration :\", [duration[i] for i in range(n)])\n",
|
||||
" print(\"end_times :\", [end_times[i].Value() for i in range(n)])\n",
|
||||
" print(\"end_time :\", end_time.Value())\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
169
examples/notebook/contrib/futoshiki.ipynb
Normal file
169
examples/notebook/contrib/futoshiki.ipynb
Normal file
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Futoshiki problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://en.wikipedia.org/wiki/Futoshiki\n",
|
||||
" '''\n",
|
||||
" The puzzle is played on a square grid, such as 5 x 5. The objective\n",
|
||||
" is to place the numbers 1 to 5 (or whatever the dimensions are)\n",
|
||||
" such that each row, and column contains each of the digits 1 to 5.\n",
|
||||
" Some digits may be given at the start. In addition, inequality\n",
|
||||
" constraints are also initially specifed between some of the squares,\n",
|
||||
" such that one must be higher or lower than its neighbour. These\n",
|
||||
" constraints must be honoured as the grid is filled out.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Also see\n",
|
||||
" http://www.guardian.co.uk/world/2006/sep/30/japan.estheraddley\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This Google CP Solver model is inspired by the Minion/Tailor\n",
|
||||
" example futoshiki.eprime.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/futoshiki.mzn\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/futoshiki.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/futoshiki.cpp\n",
|
||||
" * SICStus: http://hakank.org/sicstus/futoshiki.pl\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Futoshiki problem\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"size = len(values)\n",
|
||||
"RANGE = list(range(size))\n",
|
||||
"NUMQD = list(range(len(lt)))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"field = {}\n",
|
||||
"for i in RANGE:\n",
|
||||
" for j in RANGE:\n",
|
||||
" field[i, j] = solver.IntVar(1, size, \"field[%i,%i]\" % (i, j))\n",
|
||||
"field_flat = [field[i, j] for i in RANGE for j in RANGE]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"# set initial values\n",
|
||||
"for row in RANGE:\n",
|
||||
" for col in RANGE:\n",
|
||||
" if values[row][col] > 0:\n",
|
||||
" solver.Add(field[row, col] == values[row][col])\n",
|
||||
"\n",
|
||||
"# all rows have to be different\n",
|
||||
"for row in RANGE:\n",
|
||||
" solver.Add(solver.AllDifferent([field[row, col] for col in RANGE]))\n",
|
||||
"\n",
|
||||
"# all columns have to be different\n",
|
||||
"for col in RANGE:\n",
|
||||
" solver.Add(solver.AllDifferent([field[row, col] for row in RANGE]))\n",
|
||||
"\n",
|
||||
"# all < constraints are satisfied\n",
|
||||
"# Also: make 0-based\n",
|
||||
"for i in NUMQD:\n",
|
||||
" solver.Add(\n",
|
||||
" field[lt[i][0] - 1, lt[i][1] - 1] < field[lt[i][2] - 1, lt[i][3] - 1])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(field_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in RANGE:\n",
|
||||
" for j in RANGE:\n",
|
||||
" print(field[i, j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Example from Tailor model futoshiki.param/futoshiki.param\n",
|
||||
"# Solution:\n",
|
||||
"# 5 1 3 2 4\n",
|
||||
"# 1 4 2 5 3\n",
|
||||
"# 2 3 1 4 5\n",
|
||||
"# 3 5 4 1 2\n",
|
||||
"# 4 2 5 3 1\n",
|
||||
"#\n",
|
||||
"# Futoshiki instance, by Andras Salamon\n",
|
||||
"# specify the numbers in the grid\n",
|
||||
"#values1 = [[0, 0, 3, 2, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0],\n",
|
||||
" [0, 0, 0, 0, 0]]\n",
|
||||
"\n",
|
||||
"# [i1,j1, i2,j2] requires that values[i1,j1] < values[i2,j2]\n",
|
||||
"# Note: 1-based\n",
|
||||
"lt1 = [[1, 2, 1, 1], [1, 4, 1, 5], [2, 3, 1, 3], [3, 3, 2, 3], [3, 4, 2, 4],\n",
|
||||
" [2, 5, 3, 5], [3, 2, 4, 2], [4, 4, 4, 3], [5, 2, 5, 1], [5, 4, 5, 3],\n",
|
||||
" [5, 5, 4, 5]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Example from http://en.wikipedia.org/wiki/Futoshiki\n",
|
||||
"# Solution:\n",
|
||||
"# 5 4 3 2 1\n",
|
||||
"# 4 3 1 5 2\n",
|
||||
"# 2 1 4 3 5\n",
|
||||
"# 3 5 2 1 4\n",
|
||||
"# 1 2 5 4 3\n",
|
||||
"#\n",
|
||||
"values2 = [[0, 0, 0, 0, 0], [4, 0, 0, 0, 2], [0, 0, 4, 0, 0], [0, 0, 0, 0, 4],\n",
|
||||
" [0, 0, 0, 0, 0]]\n",
|
||||
"\n",
|
||||
"# Note: 1-based\n",
|
||||
"lt2 = [[1, 2, 1, 1], [1, 4, 1, 3], [1, 5, 1, 4], [4, 4, 4, 5], [5, 1, 5, 2],\n",
|
||||
" [5, 2, 5, 3]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
121
examples/notebook/contrib/game_theory_taha.ipynb
Normal file
121
examples/notebook/contrib/game_theory_taha.ipynb
Normal file
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Game theory in Google or-tools.\n",
|
||||
"\n",
|
||||
" 2 player zero sum game.\n",
|
||||
"\n",
|
||||
" From Taha, Operations Research (8'th edition), page 528.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CLP\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
" pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"rows = 3\n",
|
||||
"cols = 3\n",
|
||||
"\n",
|
||||
"game = [[3.0, -1.0, -3.0], [-2.0, 4.0, -1.0], [-5.0, -6.0, 2.0]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# row player\n",
|
||||
"#\n",
|
||||
"x1 = [solver.NumVar(0, 1, 'x1[%i]' % i) for i in range(rows)]\n",
|
||||
"\n",
|
||||
"v = solver.NumVar(-2, 2, 'v')\n",
|
||||
"\n",
|
||||
"for i in range(rows):\n",
|
||||
" solver.Add(v - solver.Sum([x1[j] * game[j][i] for j in range(cols)]) <= 0)\n",
|
||||
"\n",
|
||||
"solver.Add(solver.Sum(x1) == 1)\n",
|
||||
"\n",
|
||||
"objective = solver.Maximize(v)\n",
|
||||
"\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('row player:')\n",
|
||||
"print('v = ', solver.Objective().Value())\n",
|
||||
"print('Strategies: ')\n",
|
||||
"for i in range(rows):\n",
|
||||
" print(x1[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# For column player:\n",
|
||||
"#\n",
|
||||
"x2 = [solver.NumVar(0, 1, 'x2[%i]' % i) for i in range(cols)]\n",
|
||||
"\n",
|
||||
"v2 = solver.NumVar(-2, 2, 'v2')\n",
|
||||
"\n",
|
||||
"for i in range(cols):\n",
|
||||
" solver.Add(v2 - solver.Sum([x2[j] * game[i][j] for j in range(rows)]) >= 0)\n",
|
||||
"\n",
|
||||
"solver.Add(solver.Sum(x2) == 1)\n",
|
||||
"\n",
|
||||
"objective = solver.Minimize(v2)\n",
|
||||
"\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('column player:')\n",
|
||||
"print('v2 = ', solver.Objective().Value())\n",
|
||||
"print('Strategies: ')\n",
|
||||
"for i in range(rows):\n",
|
||||
" print(x2[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"print('iterations:', solver.Iterations())\n",
|
||||
"print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
104
examples/notebook/contrib/grocery.ipynb
Normal file
104
examples/notebook/contrib/grocery.ipynb
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Grocery problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Christian Schulte, Gert Smolka, Finite Domain\n",
|
||||
" http://www.mozart-oz.org/documentation/fdt/\n",
|
||||
" Constraint Programming in Oz. A Tutorial. 2001.\n",
|
||||
" '''\n",
|
||||
" A kid goes into a grocery store and buys four items. The cashier\n",
|
||||
" charges $7.11, the kid pays and is about to leave when the cashier\n",
|
||||
" calls the kid back, and says 'Hold on, I multiplied the four items\n",
|
||||
" instead of adding them; I'll try again; Hah, with adding them the\n",
|
||||
" price still comes to $7.11'. What were the prices of the four items?\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/grocery.mzn\n",
|
||||
" * Comet: http://hakank.org/comet/grocery.co\n",
|
||||
" * Zinc: http://hakank.org/minizinc/grocery.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from functools import reduce\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Grocery\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"c = 711\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"item = [solver.IntVar(0, c, \"item[%i]\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.Sum(item) == c)\n",
|
||||
"solver.Add(reduce(lambda x, y: x * y, item) == c * 100**3)\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"for i in range(1, n):\n",
|
||||
" solver.Add(item[i - 1] < item[i])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(item, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"item:\", [item[i].Value() for i in range(n)])\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
218
examples/notebook/contrib/hidato.ipynb
Normal file
218
examples/notebook/contrib/hidato.ipynb
Normal file
@@ -0,0 +1,218 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
" Hidato puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://www.shockwave.com/gamelanding/hidato.jsp\n",
|
||||
" http://www.hidato.com/\n",
|
||||
" '''\n",
|
||||
" Puzzles start semi-filled with numbered tiles.\n",
|
||||
" The first and last numbers are circled.\n",
|
||||
" Connect the numbers together to win. Consecutive\n",
|
||||
" number must touch horizontally, vertically, or\n",
|
||||
" diagonally.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/hidato.mzn\n",
|
||||
" * Gecode : http://www.hakank.org/gecode/hidato.cpp\n",
|
||||
" * Comet : http://www.hakank.org/comet/hidato.co\n",
|
||||
" * Tailopr/Essence': http://hakank.org/tailor/hidato.eprime\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/hidato.ecl\n",
|
||||
" * SICStus: http://hakank.org/sicstus/hidato.pl\n",
|
||||
"\n",
|
||||
" Note: This model is very slow. Please see Laurent Perron's much faster\n",
|
||||
" (and more elegant) model: hidato_table.py .\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"hidato\")\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"# Simple problem\n",
|
||||
"if r == 3 and c == 3:\n",
|
||||
" puzzle = [[6, 0, 9], [0, 2, 8], [1, 0, 0]]\n",
|
||||
"\n",
|
||||
"if r == 7 and c == 7:\n",
|
||||
" puzzle = [[0, 44, 41, 0, 0, 0, 0], [0, 43, 0, 28, 29, 0, 0],\n",
|
||||
" [0, 1, 0, 0, 0, 33, 0], [0, 2, 25, 4, 34, 0, 36],\n",
|
||||
" [49, 16, 0, 23, 0, 0, 0], [0, 19, 0, 0, 12, 7, 0],\n",
|
||||
" [0, 0, 0, 14, 0, 0, 0]]\n",
|
||||
"\n",
|
||||
"# Problems from the book:\n",
|
||||
"# Gyora Bededek: \"Hidato: 2000 Pure Logic Puzzles\"\n",
|
||||
"\n",
|
||||
"# Problem 1 (Practice)\n",
|
||||
"# r = 5\n",
|
||||
"# c = r\n",
|
||||
"# puzzle = [\n",
|
||||
"# [ 0, 0,20, 0, 0],\n",
|
||||
"# [ 0, 0, 0,16,18],\n",
|
||||
"# [22, 0,15, 0, 0],\n",
|
||||
"# [23, 0, 1,14,11],\n",
|
||||
"# [ 0,25, 0, 0,12],\n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"# Problem 2 (Practice)\n",
|
||||
"if r == 5 and c == 5:\n",
|
||||
" puzzle = [\n",
|
||||
" [0, 0, 0, 0, 14],\n",
|
||||
" [0, 18, 12, 0, 0],\n",
|
||||
" [0, 0, 17, 4, 5],\n",
|
||||
" [0, 0, 7, 0, 0],\n",
|
||||
" [9, 8, 25, 1, 0],\n",
|
||||
" ]\n",
|
||||
"\n",
|
||||
"# Problem 3 (Beginner)\n",
|
||||
"if r == 6 and c == 6:\n",
|
||||
" puzzle = [[0, 26, 0, 0, 0, 18], [0, 0, 27, 0, 0, 19], [31, 23, 0, 0, 14, 0],\n",
|
||||
" [0, 33, 8, 0, 15, 1], [0, 0, 0, 5, 0, 0], [35, 36, 0, 10, 0, 0]]\n",
|
||||
"\n",
|
||||
"# Problem 15 (Intermediate)\n",
|
||||
"# Note: This takes very long time to solve...\n",
|
||||
"if r == 8 and c == 8:\n",
|
||||
" puzzle = [[64, 0, 0, 0, 0, 0, 0, 0], [1, 63, 0, 59, 15, 57, 53, 0],\n",
|
||||
" [0, 4, 0, 14, 0, 0, 0, 0], [3, 0, 11, 0, 20, 19, 0, 50],\n",
|
||||
" [0, 0, 0, 0, 22, 0, 48, 40], [9, 0, 0, 32, 23, 0, 0, 41],\n",
|
||||
" [27, 0, 0, 0, 36, 0, 46, 0], [28, 30, 0, 35, 0, 0, 0, 0]]\n",
|
||||
"\n",
|
||||
"print_game(puzzle, r, c)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" x[(i, j)] = solver.IntVar(1, r * c, \"dice(%i,%i)\" % (i, j))\n",
|
||||
"x_flat = [x[(i, j)] for i in range(r) for j in range(c)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x_flat))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Fill in the clues\n",
|
||||
"#\n",
|
||||
"for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" if puzzle[i][j] > 0:\n",
|
||||
" solver.Add(x[(i, j)] == puzzle[i][j])\n",
|
||||
"\n",
|
||||
"# From the numbers k = 1 to r*c-1, find this position,\n",
|
||||
"# and then the position of k+1\n",
|
||||
"for k in range(1, r * c):\n",
|
||||
" i = solver.IntVar(0, r)\n",
|
||||
" j = solver.IntVar(0, c)\n",
|
||||
" a = solver.IntVar(-1, 1)\n",
|
||||
" b = solver.IntVar(-1, 1)\n",
|
||||
"\n",
|
||||
" # 1) First: fix \"this\" k\n",
|
||||
" # 2) and then find the position of the next value (k+1)\n",
|
||||
" # solver.Add(k == x[(i,j)])\n",
|
||||
" solver.Add(k == solver.Element(x_flat, i * c + j))\n",
|
||||
" # solver.Add(k + 1 == x[(i+a,j+b)])\n",
|
||||
" solver.Add(k + 1 == solver.Element(x_flat, (i + a) * c + (j + b)))\n",
|
||||
"\n",
|
||||
" solver.Add(i + a >= 0)\n",
|
||||
" solver.Add(j + b >= 0)\n",
|
||||
" solver.Add(i + a < r)\n",
|
||||
" solver.Add(j + b < c)\n",
|
||||
"\n",
|
||||
" # solver.Add(((a != 0) | (b != 0)))\n",
|
||||
" a_nz = solver.BoolVar()\n",
|
||||
" b_nz = solver.BoolVar()\n",
|
||||
" solver.Add(a_nz == solver.IsDifferentCstVar(a, 0))\n",
|
||||
" solver.Add(b_nz == solver.IsDifferentCstVar(b, 0))\n",
|
||||
" solver.Add(a_nz + b_nz >= 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x_flat)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(\n",
|
||||
" x_flat,\n",
|
||||
" # solver.INT_VAR_DEFAULT\n",
|
||||
" # solver.INT_VAR_SIMPLE\n",
|
||||
" # solver.CHOOSE_RANDOM\n",
|
||||
" # solver.CHOOSE_MIN_SIZE_LOWEST_MIN\n",
|
||||
" # solver.CHOOSE_MIN_SIZE_HIGHEST_MIN\n",
|
||||
" # solver.CHOOSE_MIN_SIZE_LOWEST_MAX\n",
|
||||
" # solver.CHOOSE_MIN_SIZE_HIGHEST_MAX\n",
|
||||
" # solver.CHOOSE_PATH\n",
|
||||
" solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" # solver.INT_VALUE_DEFAULT\n",
|
||||
" # solver.INT_VALUE_SIMPLE\n",
|
||||
" # solver.ASSIGN_MAX_VALUE\n",
|
||||
" # solver.ASSIGN_RANDOM_VALUE\n",
|
||||
" # solver.ASSIGN_CENTER_VALUE\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print(\"\\nSolution:\", num_solutions)\n",
|
||||
" print_board(x, r, c)\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"def print_board(x, rows, cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(\"% 2s\" % x[i, j].Value(), end=\" \")\n",
|
||||
" print(\"\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_game(game, rows, cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(\"% 2s\" % game[i][j], end=\" \")\n",
|
||||
" print(\"\")\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
125
examples/notebook/contrib/just_forgotten.ipynb
Normal file
125
examples/notebook/contrib/just_forgotten.ipynb
Normal file
@@ -0,0 +1,125 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Just forgotten puzzle (Enigma 1517) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From http://www.f1compiler.com/samples/Enigma 201517.f1.html\n",
|
||||
" '''\n",
|
||||
" Enigma 1517 Bob Walker, New Scientist magazine, October 25, 2008.\n",
|
||||
"\n",
|
||||
" Joe was furious when he forgot one of his bank account numbers.\n",
|
||||
" He remembered that it had all the digits 0 to 9 in some order,\n",
|
||||
" so he tried the following four sets without success:\n",
|
||||
"\n",
|
||||
" 9 4 6 2 1 5 7 8 3 0\n",
|
||||
" 8 6 0 4 3 9 1 2 5 7\n",
|
||||
" 1 6 4 0 2 9 7 8 5 3\n",
|
||||
" 6 8 2 4 3 1 9 0 7 5\n",
|
||||
"\n",
|
||||
" When Joe finally remembered his account number, he realised that\n",
|
||||
" in each set just four of the digits were in their correct position\n",
|
||||
" and that, if one knew that, it was possible to work out his\n",
|
||||
" account number. What was it?\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/just_forgotten.mzn\n",
|
||||
" * SICStus Prolog: http://www.hakank.org/sicstis/just_forgotten.pl\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/just_forgotten.ecl\n",
|
||||
" * Gecpde: http://hakank.org/gecode/just_forgotten.cpp\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Just forgotten\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"rows = 4\n",
|
||||
"cols = 10\n",
|
||||
"# The four tries\n",
|
||||
"a = [[9, 4, 6, 2, 1, 5, 7, 8, 3, 0], [8, 6, 0, 4, 3, 9, 1, 2, 5, 7],\n",
|
||||
" [1, 6, 4, 0, 2, 9, 7, 8, 5, 3], [6, 8, 2, 4, 3, 1, 9, 0, 7, 5]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(0, 9, \"x[%i]\" % j) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(x))\n",
|
||||
"\n",
|
||||
"for r in range(rows):\n",
|
||||
" b = [solver.IsEqualCstVar(x[c], a[r][c]) for c in range(cols)]\n",
|
||||
" solver.Add(solver.Sum(b) == 4)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" xval = [x[j].Value() for j in range(cols)]\n",
|
||||
" print(\"Account number:\")\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(\"%i \" % xval[j], end=\" \")\n",
|
||||
" print()\n",
|
||||
" print(\"\\nThe four tries, where '!' represents a correct digit:\")\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" check = \" \"\n",
|
||||
" if a[i][j] == xval[j]:\n",
|
||||
" check = \"!\"\n",
|
||||
" print(\"%i%s\" % (a[i][j], check), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
190
examples/notebook/contrib/kakuro.ipynb
Normal file
190
examples/notebook/contrib/kakuro.ipynb
Normal file
@@ -0,0 +1,190 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Kakuru puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Kakuro\n",
|
||||
" '''\n",
|
||||
" The object of the puzzle is to insert a digit from 1 to 9 inclusive\n",
|
||||
" into each white cell such that the sum of the numbers in each entry\n",
|
||||
" matches the clue associated with it and that no digit is duplicated in\n",
|
||||
" any entry. It is that lack of duplication that makes creating Kakuro\n",
|
||||
" puzzles with unique solutions possible, and which means solving a Kakuro\n",
|
||||
" puzzle involves investigating combinations more, compared to Sudoku in\n",
|
||||
" which the focus is on permutations. There is an unwritten rule for\n",
|
||||
" making Kakuro puzzles that each clue must have at least two numbers\n",
|
||||
" that add up to it. This is because including one number is mathematically\n",
|
||||
" trivial when solving Kakuro puzzles; one can simply disregard the\n",
|
||||
" number entirely and subtract it from the clue it indicates.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" This model solves the problem at the Wikipedia page.\n",
|
||||
" For a larger picture, see\n",
|
||||
" http://en.wikipedia.org/wiki/File:Kakuro_black_box.svg\n",
|
||||
"\n",
|
||||
" The solution:\n",
|
||||
" 9 7 0 0 8 7 9\n",
|
||||
" 8 9 0 8 9 5 7\n",
|
||||
" 6 8 5 9 7 0 0\n",
|
||||
" 0 6 1 0 2 6 0\n",
|
||||
" 0 0 4 6 1 3 2\n",
|
||||
" 8 9 3 1 0 1 4\n",
|
||||
" 3 1 2 0 0 2 1\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet : http://www.hakank.org/comet/kakuro.co\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/kakuro.mzn\n",
|
||||
" * SICStus : http://www.hakank.org/sicstus/kakuro.pl\n",
|
||||
" * ECLiPSe: http://www.hakank.org/eclipse/kakuro.ecl\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/kenken2.cpp\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Ensure that the sum of the segments\n",
|
||||
"# in cc == res\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def calc(cc, x, res):\n",
|
||||
"\n",
|
||||
" solver = list(x.values())[0].solver()\n",
|
||||
"\n",
|
||||
" # ensure that the values are positive\n",
|
||||
" for i in cc:\n",
|
||||
" solver.Add(x[i[0] - 1, i[1] - 1] >= 1)\n",
|
||||
"\n",
|
||||
" # sum the numbers\n",
|
||||
" solver.Add(solver.Sum([x[i[0] - 1, i[1] - 1] for i in cc]) == res)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Kakuro\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# size of matrix\n",
|
||||
"n = 7\n",
|
||||
"\n",
|
||||
"# segments\n",
|
||||
"# [sum, [segments]]\n",
|
||||
"# Note: 1-based\n",
|
||||
"problem = [[16, [1, 1], [1, 2]], [24, [1, 5], [1, 6], [1, 7]],\n",
|
||||
" [17, [2, 1], [2, 2]], [29, [2, 4], [2, 5], [2, 6], [2, 7]],\n",
|
||||
" [35, [3, 1], [3, 2], [3, 3], [3, 4], [3, 5]], [7, [4, 2], [4, 3]],\n",
|
||||
" [8, [4, 5], [4, 6]], [16, [5, 3], [5, 4], [5, 5], [5, 6], [5, 7]],\n",
|
||||
" [21, [6, 1], [6, 2], [6, 3], [6, 4]], [5, [6, 6], [6, 7]],\n",
|
||||
" [6, [7, 1], [7, 2], [7, 3]], [3, [7, 6], [7, 7]],\n",
|
||||
" [23, [1, 1], [2, 1], [3, 1]], [30, [1, 2], [2, 2], [3, 2], [4, 2]],\n",
|
||||
" [27, [1, 5], [2, 5], [3, 5], [4, 5], [5, 5]], [12, [1, 6], [2, 6]],\n",
|
||||
" [16, [1, 7], [2, 7]], [17, [2, 4], [3, 4]],\n",
|
||||
" [15, [3, 3], [4, 3], [5, 3], [6, 3], [7, 3]],\n",
|
||||
" [12, [4, 6], [5, 6], [6, 6], [7, 6]], [7, [5, 4], [6, 4]],\n",
|
||||
" [7, [5, 7], [6, 7], [7, 7]], [11, [6, 1], [7, 1]],\n",
|
||||
" [10, [6, 2], [7, 2]]]\n",
|
||||
"\n",
|
||||
"num_p = len(problem)\n",
|
||||
"\n",
|
||||
"# The blanks\n",
|
||||
"# Note: 1-based\n",
|
||||
"blanks = [[1, 3], [1, 4], [2, 3], [3, 6], [3, 7], [4, 1], [4, 4], [4, 7],\n",
|
||||
" [5, 1], [5, 2], [6, 5], [7, 4], [7, 5]]\n",
|
||||
"num_blanks = len(blanks)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the set\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(0, 9, \"x[%i,%i]\" % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# fill the blanks with 0\n",
|
||||
"for i in range(num_blanks):\n",
|
||||
" solver.Add(x[blanks[i][0] - 1, blanks[i][1] - 1] == 0)\n",
|
||||
"\n",
|
||||
"for i in range(num_p):\n",
|
||||
" segment = problem[i][1::]\n",
|
||||
" res = problem[i][0]\n",
|
||||
"\n",
|
||||
" # sum this segment\n",
|
||||
" calc(segment, x, res)\n",
|
||||
"\n",
|
||||
" # all numbers in this segment must be distinct\n",
|
||||
" segment = [x[p[0] - 1, p[1] - 1] for p in segment]\n",
|
||||
" solver.Add(solver.AllDifferent(segment))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and solution\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" val = x[i, j].Value()\n",
|
||||
" if val > 0:\n",
|
||||
" print(val, end=\" \")\n",
|
||||
" else:\n",
|
||||
" print(\" \", end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
205
examples/notebook/contrib/kenken2.ipynb
Normal file
205
examples/notebook/contrib/kenken2.ipynb
Normal file
@@ -0,0 +1,205 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" KenKen puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/KenKen\n",
|
||||
" '''\n",
|
||||
" KenKen or KEN-KEN is a style of arithmetic and logical puzzle sharing\n",
|
||||
" several characteristics with sudoku. The name comes from Japanese and\n",
|
||||
" is translated as 'square wisdom' or 'cleverness squared'.\n",
|
||||
" ...\n",
|
||||
" The objective is to fill the grid in with the digits 1 through 6 such that:\n",
|
||||
"\n",
|
||||
" * Each row contains exactly one of each digit\n",
|
||||
" * Each column contains exactly one of each digit\n",
|
||||
" * Each bold-outlined group of cells is a cage containing digits which\n",
|
||||
" achieve the specified result using the specified mathematical operation:\n",
|
||||
" addition (+),\n",
|
||||
" subtraction (-),\n",
|
||||
" multiplication (x),\n",
|
||||
" and division (/).\n",
|
||||
" (Unlike in Killer sudoku, digits may repeat within a group.)\n",
|
||||
"\n",
|
||||
" ...\n",
|
||||
" More complex KenKen problems are formed using the principles described\n",
|
||||
" above but omitting the symbols +, -, x and /, thus leaving them as\n",
|
||||
" yet another unknown to be determined.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" The solution is:\n",
|
||||
"\n",
|
||||
" 5 6 3 4 1 2\n",
|
||||
" 6 1 4 5 2 3\n",
|
||||
" 4 5 2 3 6 1\n",
|
||||
" 3 4 1 2 5 6\n",
|
||||
" 2 3 6 1 4 5\n",
|
||||
" 1 2 5 6 3 4\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"from functools import reduce\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Ensure that the sum of the segments\n",
|
||||
"# in cc == res\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def calc(cc, x, res):\n",
|
||||
"\n",
|
||||
" solver = list(x.values())[0].solver()\n",
|
||||
"\n",
|
||||
" if len(cc) == 2:\n",
|
||||
"\n",
|
||||
" # for two operands there may be\n",
|
||||
" # a lot of variants\n",
|
||||
"\n",
|
||||
" c00, c01 = cc[0]\n",
|
||||
" c10, c11 = cc[1]\n",
|
||||
" a = x[c00 - 1, c01 - 1]\n",
|
||||
" b = x[c10 - 1, c11 - 1]\n",
|
||||
"\n",
|
||||
" r1 = solver.IsEqualCstVar(a + b, res)\n",
|
||||
" r2 = solver.IsEqualCstVar(a * b, res)\n",
|
||||
" r3 = solver.IsEqualVar(a * res, b)\n",
|
||||
" r4 = solver.IsEqualVar(b * res, a)\n",
|
||||
" r5 = solver.IsEqualCstVar(a - b, res)\n",
|
||||
" r6 = solver.IsEqualCstVar(b - a, res)\n",
|
||||
" solver.Add(r1 + r2 + r3 + r4 + r5 + r6 >= 1)\n",
|
||||
"\n",
|
||||
" else:\n",
|
||||
"\n",
|
||||
" # res is either sum or product of the segment\n",
|
||||
"\n",
|
||||
" xx = [x[i[0] - 1, i[1] - 1] for i in cc]\n",
|
||||
"\n",
|
||||
" # Sum\n",
|
||||
" # # SumEquality don't work:\n",
|
||||
" # this_sum = solver.SumEquality(xx, res)\n",
|
||||
" this_sum = solver.IsEqualCstVar(solver.Sum(xx), res)\n",
|
||||
"\n",
|
||||
" # Product\n",
|
||||
" # # Prod (or MakeProd) don't work:\n",
|
||||
" # this_prod = solver.IsEqualCstVar(solver.Prod(xx), res)\n",
|
||||
" this_prod = solver.IsEqualCstVar(reduce(lambda a, b: a * b, xx), res)\n",
|
||||
" solver.Add(this_sum + this_prod >= 1)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"KenKen\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# size of matrix\n",
|
||||
"n = 6\n",
|
||||
"\n",
|
||||
"# For a better view of the problem, see\n",
|
||||
"# http://en.wikipedia.org/wiki/File:KenKenProblem.svg\n",
|
||||
"\n",
|
||||
"# hints\n",
|
||||
"# [sum, [segments]]\n",
|
||||
"# Note: 1-based\n",
|
||||
"problem = [[11, [[1, 1], [2, 1]]], [2, [[1, 2], [1, 3]]],\n",
|
||||
" [20, [[1, 4], [2, 4]]], [6, [[1, 5], [1, 6], [2, 6], [3, 6]]],\n",
|
||||
" [3, [[2, 2], [2, 3]]], [3, [[2, 5], [3, 5]]],\n",
|
||||
" [240, [[3, 1], [3, 2], [4, 1], [4, 2]]], [6, [[3, 3], [3, 4]]],\n",
|
||||
" [6, [[4, 3], [5, 3]]], [7, [[4, 4], [5, 4], [5, 5]]],\n",
|
||||
" [30, [[4, 5], [4, 6]]], [6, [[5, 1], [5, 2]]],\n",
|
||||
" [9, [[5, 6], [6, 6]]], [8, [[6, 1], [6, 2], [6, 3]]],\n",
|
||||
" [2, [[6, 4], [6, 5]]]]\n",
|
||||
"\n",
|
||||
"num_p = len(problem)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the set\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(1, n, \"x[%i,%i]\" % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# all rows and columns must be unique\n",
|
||||
"for i in range(n):\n",
|
||||
" row = [x[i, j] for j in range(n)]\n",
|
||||
" solver.Add(solver.AllDifferent(row))\n",
|
||||
"\n",
|
||||
" col = [x[j, i] for j in range(n)]\n",
|
||||
" solver.Add(solver.AllDifferent(col))\n",
|
||||
"\n",
|
||||
"# calculate the segments\n",
|
||||
"for (res, segment) in problem:\n",
|
||||
" calc(segment, x, res)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and solution\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(x[i, j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
200
examples/notebook/contrib/killer_sudoku.ipynb
Normal file
200
examples/notebook/contrib/killer_sudoku.ipynb
Normal file
@@ -0,0 +1,200 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Killer Sudoku in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Killer_Sudoku\n",
|
||||
" '''\n",
|
||||
" Killer sudoku (also killer su doku, sumdoku, sum doku, addoku, or\n",
|
||||
" samunamupure) is a puzzle that combines elements of sudoku and kakuro.\n",
|
||||
" Despite the name, the simpler killer sudokus can be easier to solve\n",
|
||||
" than regular sudokus, depending on the solver's skill at mental arithmetic;\n",
|
||||
" the hardest ones, however, can take hours to crack.\n",
|
||||
"\n",
|
||||
" ...\n",
|
||||
"\n",
|
||||
" The objective is to fill the grid with numbers from 1 to 9 in a way that\n",
|
||||
" the following conditions are met:\n",
|
||||
"\n",
|
||||
" * Each row, column, and nonet contains each number exactly once.\n",
|
||||
" * The sum of all numbers in a cage must match the small number printed\n",
|
||||
" in its corner.\n",
|
||||
" * No number appears more than once in a cage. (This is the standard rule\n",
|
||||
" for killer sudokus, and implies that no cage can include more\n",
|
||||
" than 9 cells.)\n",
|
||||
"\n",
|
||||
" In 'Killer X', an additional rule is that each of the long diagonals\n",
|
||||
" contains each number once.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Here we solve the problem from the Wikipedia page, also shown here\n",
|
||||
" http://en.wikipedia.org/wiki/File:Killersudoku_color.svg\n",
|
||||
"\n",
|
||||
" The output is:\n",
|
||||
" 2 1 5 6 4 7 3 9 8\n",
|
||||
" 3 6 8 9 5 2 1 7 4\n",
|
||||
" 7 9 4 3 8 1 6 5 2\n",
|
||||
" 5 8 6 2 7 4 9 3 1\n",
|
||||
" 1 4 2 5 9 3 8 6 7\n",
|
||||
" 9 7 3 8 1 6 4 2 5\n",
|
||||
" 8 2 1 7 3 9 5 4 6\n",
|
||||
" 6 5 9 4 2 8 7 1 3\n",
|
||||
" 4 3 7 1 6 5 2 8 9\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet : http://www.hakank.org/comet/killer_sudoku.co\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/killer_sudoku.mzn\n",
|
||||
" * SICStus: http://www.hakank.org/sicstus/killer_sudoku.pl\n",
|
||||
" * ECLiPSE: http://www.hakank.org/eclipse/killer_sudoku.ecl\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/killer_sudoku.cpp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Ensure that the sum of the segments\n",
|
||||
"# in cc == res\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def calc(cc, x, res):\n",
|
||||
"\n",
|
||||
" solver = list(x.values())[0].solver()\n",
|
||||
"\n",
|
||||
" # sum the numbers\n",
|
||||
" cage = [x[i[0] - 1, i[1] - 1] for i in cc]\n",
|
||||
" solver.Add(solver.Sum(cage) == res)\n",
|
||||
" solver.Add(solver.AllDifferent(cage))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Killer Sudoku\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# size of matrix\n",
|
||||
"n = 9\n",
|
||||
"\n",
|
||||
"# For a better view of the problem, see\n",
|
||||
"# http://en.wikipedia.org/wiki/File:Killersudoku_color.svg\n",
|
||||
"\n",
|
||||
"# hints\n",
|
||||
"# [sum, [segments]]\n",
|
||||
"# Note: 1-based\n",
|
||||
"problem = [[3, [[1, 1], [1, 2]]], [15, [[1, 3], [1, 4], [1, 5]]],\n",
|
||||
" [22, [[1, 6], [2, 5], [2, 6], [3, 5]]], [4, [[1, 7], [2, 7]]],\n",
|
||||
" [16, [[1, 8], [2, 8]]], [15, [[1, 9], [2, 9], [3, 9], [4, 9]]],\n",
|
||||
" [25, [[2, 1], [2, 2], [3, 1], [3, 2]]], [17, [[2, 3], [2, 4]]],\n",
|
||||
" [9, [[3, 3], [3, 4], [4, 4]]], [8, [[3, 6], [4, 6], [5, 6]]],\n",
|
||||
" [20, [[3, 7], [3, 8], [4, 7]]], [6, [[4, 1], [5, 1]]],\n",
|
||||
" [14, [[4, 2], [4, 3]]], [17, [[4, 5], [5, 5], [6, 5]]],\n",
|
||||
" [17, [[4, 8], [5, 7], [5, 8]]], [13, [[5, 2], [5, 3], [6, 2]]],\n",
|
||||
" [20, [[5, 4], [6, 4], [7, 4]]], [12, [[5, 9], [6, 9]]],\n",
|
||||
" [27, [[6, 1], [7, 1], [8, 1], [9, 1]]],\n",
|
||||
" [6, [[6, 3], [7, 2], [7, 3]]], [20, [[6, 6], [7, 6], [7, 7]]],\n",
|
||||
" [6, [[6, 7], [6, 8]]], [10, [[7, 5], [8, 4], [8, 5], [9, 4]]],\n",
|
||||
" [14, [[7, 8], [7, 9], [8, 8], [8, 9]]], [8, [[8, 2], [9, 2]]],\n",
|
||||
" [16, [[8, 3], [9, 3]]], [15, [[8, 6], [8, 7]]],\n",
|
||||
" [13, [[9, 5], [9, 6], [9, 7]]], [17, [[9, 8], [9, 9]]]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the set\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[i, j] = solver.IntVar(1, n, \"x[%i,%i]\" % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# all rows and columns must be unique\n",
|
||||
"for i in range(n):\n",
|
||||
" row = [x[i, j] for j in range(n)]\n",
|
||||
" solver.Add(solver.AllDifferent(row))\n",
|
||||
"\n",
|
||||
" col = [x[j, i] for j in range(n)]\n",
|
||||
" solver.Add(solver.AllDifferent(col))\n",
|
||||
"\n",
|
||||
"# cells\n",
|
||||
"for i in range(2):\n",
|
||||
" for j in range(2):\n",
|
||||
" cell = [\n",
|
||||
" x[r, c]\n",
|
||||
" for r in range(i * 3, i * 3 + 3)\n",
|
||||
" for c in range(j * 3, j * 3 + 3)\n",
|
||||
" ]\n",
|
||||
" solver.Add(solver.AllDifferent(cell))\n",
|
||||
"\n",
|
||||
"# calculate the segments\n",
|
||||
"for (res, segment) in problem:\n",
|
||||
" calc(segment, x, res)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and solution\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(x[i, j].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
102
examples/notebook/contrib/knapsack_cp.ipynb
Normal file
102
examples/notebook/contrib/knapsack_cp.ipynb
Normal file
@@ -0,0 +1,102 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Knapsack problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Simple knapsack problem.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def knapsack(solver, values, weights, n):\n",
|
||||
" z = solver.IntVar(0, 10000)\n",
|
||||
" x = [solver.IntVar(0, 1, \"x(%i)\" % i) for i in range(len(values))]\n",
|
||||
" solver.Add(z >= 0)\n",
|
||||
" solver.Add(z == solver.ScalProd(x, values))\n",
|
||||
" solver.Add(solver.ScalProd(x, weights) <= n)\n",
|
||||
"\n",
|
||||
" return [x, z]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"knapsack_cp\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print(\"values:\", values)\n",
|
||||
"print(\"weights:\", weights)\n",
|
||||
"print(\"n:\", n)\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"[x, z] = knapsack(solver, values, weights, n)\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Maximize(z, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(z)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MAX_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"x:\", [x[i].Value() for i in range(len(values))])\n",
|
||||
" print(\"z:\", z.Value())\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"values = [15, 100, 90, 60, 40, 15, 10, 1, 12, 12, 100]\n",
|
||||
"weights = [2, 20, 20, 30, 40, 30, 60, 10, 21, 12, 2]\n",
|
||||
"n = 102\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
112
examples/notebook/contrib/knapsack_mip.ipynb
Normal file
112
examples/notebook/contrib/knapsack_mip.ipynb
Normal file
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Knapsack problem using MIP in Google or-tools.\n",
|
||||
"\n",
|
||||
" From the OPL model knapsack.mod\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CBC\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCBC',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"nb_items = 12\n",
|
||||
"nb_resources = 7\n",
|
||||
"items = list(range(nb_items))\n",
|
||||
"resources = list(range(nb_resources))\n",
|
||||
"\n",
|
||||
"capacity = [18209, 7692, 1333, 924, 26638, 61188, 13360]\n",
|
||||
"value = [96, 76, 56, 11, 86, 10, 66, 86, 83, 12, 9, 81]\n",
|
||||
"use = [[19, 1, 10, 1, 1, 14, 152, 11, 1, 1, 1, 1],\n",
|
||||
" [0, 4, 53, 0, 0, 80, 0, 4, 5, 0, 0, 0],\n",
|
||||
" [4, 660, 3, 0, 30, 0, 3, 0, 4, 90, 0, 0],\n",
|
||||
" [7, 0, 18, 6, 770, 330, 7, 0, 0, 6, 0, 0],\n",
|
||||
" [0, 20, 0, 4, 52, 3, 0, 0, 0, 5, 4, 0],\n",
|
||||
" [0, 0, 40, 70, 4, 63, 0, 0, 60, 0, 4, 0],\n",
|
||||
" [0, 32, 0, 0, 0, 5, 0, 3, 0, 660, 0, 9]]\n",
|
||||
"\n",
|
||||
"max_value = max(capacity)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"take = [solver.IntVar(0, max_value, 'take[%i]' % j) for j in items]\n",
|
||||
"\n",
|
||||
"# total cost, to be maximized\n",
|
||||
"z = solver.Sum([value[i] * take[i] for i in items])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for r in resources:\n",
|
||||
" solver.Add(solver.Sum([use[r][i] * take[i] for i in items]) <= capacity[r])\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Maximize(z)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('z: ', int(solver.Objective().Value()))\n",
|
||||
"\n",
|
||||
"print('take:', end=' ')\n",
|
||||
"for i in items:\n",
|
||||
" print(int(take[i].SolutionValue()), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
147
examples/notebook/contrib/labeled_dice.ipynb
Normal file
147
examples/notebook/contrib/labeled_dice.ipynb
Normal file
@@ -0,0 +1,147 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Labeled dice problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Jim Orlin 'Colored letters, labeled dice: a logic puzzle'\n",
|
||||
" http://jimorlin.wordpress.com/2009/02/17/colored-letters-labeled-dice-a-logic-puzzle/\n",
|
||||
" '''\n",
|
||||
" My daughter Jenn bough a puzzle book, and showed me a cute puzzle. There\n",
|
||||
" are 13 words as follows: BUOY, CAVE, CELT, FLUB, FORK, HEMP, JUDY,\n",
|
||||
" JUNK, LIMN, QUIP, SWAG, VISA, WISH.\n",
|
||||
"\n",
|
||||
" There are 24 different letters that appear in the 13 words. The question\n",
|
||||
" is: can one assign the 24 letters to 4 different cubes so that the\n",
|
||||
" four letters of each word appears on different cubes. (There is one\n",
|
||||
" letter from each word on each cube.) It might be fun for you to try\n",
|
||||
" it. I'll give a small hint at the end of this post. The puzzle was\n",
|
||||
" created by Humphrey Dudley.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Jim Orlin's followup 'Update on Logic Puzzle':\n",
|
||||
" http://jimorlin.wordpress.com/2009/02/21/update-on-logic-puzzle/\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/labeled_dice.ecl\n",
|
||||
" * Comet : http://www.hakank.org/comet/labeled_dice.co\n",
|
||||
" * Gecode : http://hakank.org/gecode/labeled_dice.cpp\n",
|
||||
" * SICStus: http://hakank.org/sicstus/labeled_dice.pl\n",
|
||||
" * Zinc : http://hakank.org/minizinc/labeled_dice.zinc\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Labeled dice\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 4\n",
|
||||
"m = 24\n",
|
||||
"A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, Y = (\n",
|
||||
" list(range(m)))\n",
|
||||
"letters = [\n",
|
||||
" \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\", \"K\", \"L\", \"M\", \"N\", \"O\",\n",
|
||||
" \"P\", \"Q\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"Y\"\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"num_words = 13\n",
|
||||
"words = [[B, U, O, Y], [C, A, V, E], [C, E, L, T], [F, L, U, B], [F, O, R, K],\n",
|
||||
" [H, E, M, P], [J, U, D, Y], [J, U, N, K], [L, I, M, N], [Q, U, I, P],\n",
|
||||
" [S, W, A, G], [V, I, S, A], [W, I, S, H]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"dice = [solver.IntVar(0, n - 1, \"dice[%i]\" % i) for i in range(m)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# the letters in a word must be on a different die\n",
|
||||
"for i in range(num_words):\n",
|
||||
" solver.Add(solver.AllDifferent([dice[words[i][j]] for j in range(n)]))\n",
|
||||
"\n",
|
||||
"# there must be exactly 6 letters of each die\n",
|
||||
"for i in range(n):\n",
|
||||
" b = [solver.IsEqualCstVar(dice[j], i) for j in range(m)]\n",
|
||||
" solver.Add(solver.Sum(b) == 6)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(dice)\n",
|
||||
"\n",
|
||||
"db = solver.Phase(dice, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# result\n",
|
||||
"#\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" # print \"dice:\", [(letters[i],dice[i].Value()) for i in range(m)]\n",
|
||||
" for d in range(n):\n",
|
||||
" print(\"die %i:\" % d, end=\" \")\n",
|
||||
" for i in range(m):\n",
|
||||
" if dice[i].Value() == d:\n",
|
||||
" print(letters[i], end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print(\"The words with the cube label:\")\n",
|
||||
" for i in range(num_words):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(\n",
|
||||
" \"%s (%i)\" % (letters[words[i][j]], dice[words[i][j]].Value()),\n",
|
||||
" end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
119
examples/notebook/contrib/langford.ipynb
Normal file
119
examples/notebook/contrib/langford.ipynb
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Langford's number problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Langford's number problem (CSP lib problem 24)\n",
|
||||
" http://www.csplib.org/prob/prob024/\n",
|
||||
" '''\n",
|
||||
" Arrange 2 sets of positive integers 1..k to a sequence,\n",
|
||||
" such that, following the first occurence of an integer i,\n",
|
||||
" each subsequent occurrence of i, appears i+1 indices later\n",
|
||||
" than the last.\n",
|
||||
" For example, for k=4, a solution would be 41312432\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" * John E. Miller: Langford's Problem\n",
|
||||
" http://www.lclark.edu/~miller/langford.html\n",
|
||||
"\n",
|
||||
" * Encyclopedia of Integer Sequences for the number of solutions for each k\n",
|
||||
" http://www.research.att.com/cgi-bin/access.cgi/as/njas/sequences/eisA.cgi?Anum=014552\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Also, see the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/langford2.mzn\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/langford.rb\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/langford.ecl\n",
|
||||
" * SICStus: http://hakank.org/sicstus/langford.pl\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Langford\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print(\"k:\", k)\n",
|
||||
"p = list(range(2 * k))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"position = [solver.IntVar(0, 2 * k - 1, \"position[%i]\" % i) for i in p]\n",
|
||||
"solution = [solver.IntVar(1, k, \"position[%i]\" % i) for i in p]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(position))\n",
|
||||
"\n",
|
||||
"for i in range(1, k + 1):\n",
|
||||
" solver.Add(position[i + k - 1] == position[i - 1] + i + 1)\n",
|
||||
" solver.Add(solver.Element(solution, position[i - 1]) == i)\n",
|
||||
" solver.Add(solver.Element(solution, position[k + i - 1]) == i)\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"solver.Add(solution[0] < solution[2 * k - 1])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# search and result\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(position, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"solution:\", \",\".join([str(solution[i].Value()) for i in p]))\n",
|
||||
" num_solutions += 1\n",
|
||||
" if num_sol > 0 and num_solutions >= num_sol:\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"k = 8\n",
|
||||
"num_sol = 0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
126
examples/notebook/contrib/least_diff.ipynb
Normal file
126
examples/notebook/contrib/least_diff.ipynb
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Least diff problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" This model solves the following problem:\n",
|
||||
"\n",
|
||||
" What is the smallest difference between two numbers X - Y\n",
|
||||
" if you must use all the digits (0..9) exactly once.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Choco : http://www.hakank.org/choco/LeastDiff2.java\n",
|
||||
" * ECLiPSE : http://www.hakank.org/eclipse/least_diff2.ecl\n",
|
||||
" * Comet : http://www.hakank.org/comet/least_diff.co\n",
|
||||
" * Tailor/Essence': http://www.hakank.org/tailor/leastDiff.eprime\n",
|
||||
" * Gecode : http://www.hakank.org/gecode/least_diff.cpp\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/least_diff.rb\n",
|
||||
" * JaCoP : http://www.hakank.org/JaCoP/LeastDiff.java\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/least_diff.mzn\n",
|
||||
" * SICStus : http://www.hakank.org/sicstus/least_diff.pl\n",
|
||||
" * Zinc : http://hakank.org/minizinc/least_diff.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_cp_solver/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Least diff\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"digits = list(range(0, 10))\n",
|
||||
"a = solver.IntVar(digits, \"a\")\n",
|
||||
"b = solver.IntVar(digits, \"b\")\n",
|
||||
"c = solver.IntVar(digits, \"c\")\n",
|
||||
"d = solver.IntVar(digits, \"d\")\n",
|
||||
"e = solver.IntVar(digits, \"e\")\n",
|
||||
"\n",
|
||||
"f = solver.IntVar(digits, \"f\")\n",
|
||||
"g = solver.IntVar(digits, \"g\")\n",
|
||||
"h = solver.IntVar(digits, \"h\")\n",
|
||||
"i = solver.IntVar(digits, \"i\")\n",
|
||||
"j = solver.IntVar(digits, \"j\")\n",
|
||||
"\n",
|
||||
"letters = [a, b, c, d, e, f, g, h, i, j]\n",
|
||||
"\n",
|
||||
"digit_vector = [10000, 1000, 100, 10, 1]\n",
|
||||
"x = solver.ScalProd(letters[0:5], digit_vector)\n",
|
||||
"y = solver.ScalProd(letters[5:], digit_vector)\n",
|
||||
"diff = x - y\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(diff > 0)\n",
|
||||
"solver.Add(solver.AllDifferent(letters))\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(diff, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(letters)\n",
|
||||
"solution.Add(x)\n",
|
||||
"solution.Add(y)\n",
|
||||
"solution.Add(diff)\n",
|
||||
"\n",
|
||||
"# last solution since it's a minimization problem\n",
|
||||
"collector = solver.LastSolutionCollector(solution)\n",
|
||||
"search_log = solver.SearchLog(100, diff)\n",
|
||||
"# Note: I'm not sure what CHOOSE_PATH do, but it is fast:\n",
|
||||
"# find the solution in just 4 steps\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase(letters, solver.CHOOSE_PATH, solver.ASSIGN_MIN_VALUE),\n",
|
||||
" [objective, search_log, collector])\n",
|
||||
"\n",
|
||||
"# get the first (and only) solution\n",
|
||||
"\n",
|
||||
"xval = collector.Value(0, x)\n",
|
||||
"yval = collector.Value(0, y)\n",
|
||||
"diffval = collector.Value(0, diff)\n",
|
||||
"print(\"x:\", xval)\n",
|
||||
"print(\"y:\", yval)\n",
|
||||
"print(\"diff:\", diffval)\n",
|
||||
"print(xval, \"-\", yval, \"=\", diffval)\n",
|
||||
"print([(\"abcdefghij\" [i], collector.Value(0, letters[i])) for i in range(10)])\n",
|
||||
"print()\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
104
examples/notebook/contrib/least_square.ipynb
Normal file
104
examples/notebook/contrib/least_square.ipynb
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Least square optimization problem in Google or-tools.\n",
|
||||
"\n",
|
||||
" Solving a fourth grade least square equation.\n",
|
||||
"\n",
|
||||
" From the Swedish book 'Optimeringslara' [Optimization Theory],\n",
|
||||
" page 286f.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CLP\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
" pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"# data\n",
|
||||
"# number of points\n",
|
||||
"num = 14\n",
|
||||
"\n",
|
||||
"# temperature\n",
|
||||
"t = [20, 30, 80, 125, 175, 225, 275, 325, 360, 420, 495, 540, 630, 700]\n",
|
||||
"\n",
|
||||
"# percentage gas\n",
|
||||
"F = [\n",
|
||||
" 0.0, 5.8, 14.7, 31.6, 43.2, 58.3, 78.4, 89.4, 96.4, 99.1, 99.5, 99.9,\n",
|
||||
" 100.0, 100.0\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"p = 4\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"a = [solver.NumVar(-100, 100, 'a[%i]' % i) for i in range(p + 1)]\n",
|
||||
"\n",
|
||||
"# to minimize\n",
|
||||
"z = solver.Sum([\n",
|
||||
" (F[i] - (sum([a[j] * t[i]**j for j in range(p + 1)]))) for i in range(num)\n",
|
||||
"])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.Sum([20**i * a[i] for i in range(p + 1)]) == 0)\n",
|
||||
"\n",
|
||||
"solver.Add((a[0] + sum([700.0**j * a[j] for j in range(1, p + 1)])) == 100.0)\n",
|
||||
"\n",
|
||||
"for i in range(num):\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([j * a[j] * t[i]**(j - 1) for j in range(p + 1)]) >= 0)\n",
|
||||
"\n",
|
||||
"objective = solver.Minimize(z)\n",
|
||||
"\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('z = ', solver.Objective().Value())\n",
|
||||
"for i in range(p + 1):\n",
|
||||
" print(a[i].SolutionValue(), end=' ')\n",
|
||||
"print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
134
examples/notebook/contrib/lectures.ipynb
Normal file
134
examples/notebook/contrib/lectures.ipynb
Normal file
@@ -0,0 +1,134 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Lectures problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Biggs: Discrete Mathematics (2nd ed), page 187.\n",
|
||||
" '''\n",
|
||||
" Suppose we wish to schedule six one-hour lectures, v1, v2, v3, v4, v5, v6.\n",
|
||||
" Among the the potential audience there are people who wish to hear both\n",
|
||||
"\n",
|
||||
" - v1 and v2\n",
|
||||
" - v1 and v4\n",
|
||||
" - v3 and v5\n",
|
||||
" - v2 and v6\n",
|
||||
" - v4 and v5\n",
|
||||
" - v5 and v6\n",
|
||||
" - v1 and v6\n",
|
||||
"\n",
|
||||
" How many hours are necessary in order that the lectures can be given\n",
|
||||
" without clashes?\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/lectures.mzn\n",
|
||||
" * SICstus: http://hakank.org/sicstus/lectures.pl\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/lectures.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/lectures.cpp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Lectures')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# The schedule requirements:\n",
|
||||
"# lecture a cannot be held at the same time as b\n",
|
||||
"# Note: 1-based\n",
|
||||
"g = [[1, 2], [1, 4], [3, 5], [2, 6], [4, 5], [5, 6], [1, 6]]\n",
|
||||
"\n",
|
||||
"# number of nodes\n",
|
||||
"n = 6\n",
|
||||
"\n",
|
||||
"# number of edges\n",
|
||||
"edges = len(g)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"v = [solver.IntVar(0, n - 1, 'v[%i]' % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"# maximum color, to minimize\n",
|
||||
"# Note: since Python is 0-based, the\n",
|
||||
"# number of colors is +1\n",
|
||||
"max_c = solver.IntVar(0, n - 1, 'max_c')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(max_c == solver.Max(v))\n",
|
||||
"\n",
|
||||
"# ensure that there are no clashes\n",
|
||||
"# also, adjust to 0-base\n",
|
||||
"for i in range(edges):\n",
|
||||
" solver.Add(v[g[i][0] - 1] != v[g[i][1] - 1])\n",
|
||||
"\n",
|
||||
"# symmetry breaking:\n",
|
||||
"# - v0 has the color 0,\n",
|
||||
"# - v1 has either color 0 or 1\n",
|
||||
"solver.Add(v[0] == 0)\n",
|
||||
"solver.Add(v[1] <= 1)\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Minimize(max_c, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(v, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_CENTER_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('max_c:', max_c.Value() + 1, 'colors')\n",
|
||||
" print('v:', [v[i].Value() for i in range(n)])\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
65
examples/notebook/contrib/magic_sequence_sat.ipynb
Normal file
65
examples/notebook/contrib/magic_sequence_sat.ipynb
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2018 Gergo Rozner\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",
|
||||
"\"\"\"Solve the magic sequence problem with the CP-SAT solver.\"\"\"\n",
|
||||
"\n",
|
||||
"from __future__ import absolute_import\n",
|
||||
"from __future__ import division\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\"\"\"Magic sequence problem.\"\"\"\n",
|
||||
"n = 100\n",
|
||||
"values = range(n)\n",
|
||||
"\n",
|
||||
"model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
"x = [model.NewIntVar(0, n, 'x%i' % i) for i in values]\n",
|
||||
"\n",
|
||||
"for k in values:\n",
|
||||
" tmp_array = []\n",
|
||||
" for i in values:\n",
|
||||
" tmp_var = model.NewBoolVar('')\n",
|
||||
" model.Add(x[i] == k).OnlyEnforceIf(tmp_var)\n",
|
||||
" model.Add(x[i] != k).OnlyEnforceIf(tmp_var.Not())\n",
|
||||
" tmp_array.append(tmp_var)\n",
|
||||
" model.Add(sum(tmp_array) == x[k])\n",
|
||||
"\n",
|
||||
"# Redundant constraint.\n",
|
||||
"model.Add(sum(x) == n)\n",
|
||||
"\n",
|
||||
"solver = cp_model.CpSolver()\n",
|
||||
"# No solution printer, this problem has only 1 solution.\n",
|
||||
"solver.parameters.log_search_progress = True\n",
|
||||
"solver.Solve(model)\n",
|
||||
"print(solver.ResponseStats())\n",
|
||||
"for k in values:\n",
|
||||
" print('x[%i] = %i ' % (k, solver.Value(x[k])), end='')\n",
|
||||
"print()\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
119
examples/notebook/contrib/magic_square.ipynb
Normal file
119
examples/notebook/contrib/magic_square.ipynb
Normal file
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Magic squares in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Magic square problem.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[(i, j)] = solver.IntVar(1, n * n, \"x(%i,%i)\" % (i, j))\n",
|
||||
"x_flat = [x[(i, j)] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"# the sum\n",
|
||||
"# s = ( n * (n*n + 1)) / 2\n",
|
||||
"s = solver.IntVar(1, n * n * n, \"s\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"# solver.Add(s == ( n * (n*n + 1)) / 2)\n",
|
||||
"\n",
|
||||
"solver.Add(solver.AllDifferent(x_flat))\n",
|
||||
"\n",
|
||||
"[solver.Add(solver.Sum([x[(i, j)] for j in range(n)]) == s) for i in range(n)]\n",
|
||||
"[solver.Add(solver.Sum([x[(i, j)] for i in range(n)]) == s) for j in range(n)]\n",
|
||||
"\n",
|
||||
"solver.Add(solver.Sum([x[(i, i)] for i in range(n)]) == s) # diag 1\n",
|
||||
"solver.Add(solver.Sum([x[(i, n - i - 1)] for i in range(n)]) == s) # diag 2\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"# solver.Add(x[(0,0)] == 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x_flat)\n",
|
||||
"solution.Add(s)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(\n",
|
||||
" x_flat,\n",
|
||||
" # solver.INT_VAR_DEFAULT,\n",
|
||||
" solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" # solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n",
|
||||
"\n",
|
||||
" # solver.ASSIGN_MIN_VALUE\n",
|
||||
" solver.ASSIGN_CENTER_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"s:\", s.Value())\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(\"%2i\" % x[(i, j)].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
" if num_solutions > limit:\n",
|
||||
" break\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"n = 4\n",
|
||||
"limit=100\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
120
examples/notebook/contrib/magic_square_and_cards.ipynb
Normal file
120
examples/notebook/contrib/magic_square_and_cards.ipynb
Normal file
@@ -0,0 +1,120 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Magic squares and cards problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" Martin Gardner (July 1971)\n",
|
||||
" '''\n",
|
||||
" Allowing duplicates values, what is the largest constant sum for an order-3\n",
|
||||
" magic square that can be formed with nine cards from the deck.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"# n = 3\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" x[(i, j)] = solver.IntVar(1, 13, \"x(%i,%i)\" % (i, j))\n",
|
||||
"x_flat = [x[(i, j)] for i in range(n) for j in range(n)]\n",
|
||||
"\n",
|
||||
"s = solver.IntVar(1, 13 * 4, \"s\")\n",
|
||||
"counts = [solver.IntVar(0, 4, \"counts(%i)\" % i) for i in range(14)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.Distribute(x_flat, list(range(14)), counts))\n",
|
||||
"\n",
|
||||
"# the standard magic square constraints (sans all_different)\n",
|
||||
"[solver.Add(solver.Sum([x[(i, j)] for j in range(n)]) == s) for i in range(n)]\n",
|
||||
"[solver.Add(solver.Sum([x[(i, j)] for i in range(n)]) == s) for j in range(n)]\n",
|
||||
"\n",
|
||||
"solver.Add(solver.Sum([x[(i, i)] for i in range(n)]) == s) # diag 1\n",
|
||||
"solver.Add(solver.Sum([x[(i, n - i - 1)] for i in range(n)]) == s) # diag 2\n",
|
||||
"\n",
|
||||
"# redundant constraint\n",
|
||||
"solver.Add(solver.Sum(counts) == n * n)\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"objective = solver.Maximize(s, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add(x_flat)\n",
|
||||
"solution.Add(s)\n",
|
||||
"solution.Add(counts)\n",
|
||||
"\n",
|
||||
"# db: DecisionBuilder\n",
|
||||
"db = solver.Phase(x_flat, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MAX_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"s:\", s.Value())\n",
|
||||
" print(\"counts:\", [counts[i].Value() for i in range(14)])\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(x[(i, j)].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"n = 3\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
199
examples/notebook/contrib/magic_square_mip.ipynb
Normal file
199
examples/notebook/contrib/magic_square_mip.ipynb
Normal file
@@ -0,0 +1,199 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2011 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Magic square (integer programming) in Google or-tools.\n",
|
||||
"\n",
|
||||
" Translated from GLPK:s example magic.mod\n",
|
||||
" '''\n",
|
||||
" MAGIC, Magic Square\n",
|
||||
"\n",
|
||||
" Written in GNU MathProg by Andrew Makhorin <mao@mai2.rcnet.ru>\n",
|
||||
"\n",
|
||||
" In recreational mathematics, a magic square of order n is an\n",
|
||||
" arrangement of n^2 numbers, usually distinct integers, in a square,\n",
|
||||
" such that n numbers in all rows, all columns, and both diagonals sum\n",
|
||||
" to the same constant. A normal magic square contains the integers\n",
|
||||
" from 1 to n^2.\n",
|
||||
"\n",
|
||||
" (From Wikipedia, the free encyclopedia.)\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare to the CP version:\n",
|
||||
" http://www.hakank.org/google_or_tools/magic_square.py\n",
|
||||
"\n",
|
||||
" Here we also experiment with how long it takes when\n",
|
||||
" using an output_matrix (much longer).\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.linear_solver import pywraplp\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# main(n, use_output_matrix)\n",
|
||||
"# n: size of matrix\n",
|
||||
"# use_output_matrix: use the output_matrix\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"\n",
|
||||
"print('Solver: ', sol)\n",
|
||||
"\n",
|
||||
"# using GLPK\n",
|
||||
"if sol == 'GLPK':\n",
|
||||
" solver = pywraplp.Solver('CoinsGridGLPK',\n",
|
||||
" pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"else:\n",
|
||||
" # Using CLP\n",
|
||||
" solver = pywraplp.Solver('CoinsGridCLP',\n",
|
||||
" pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print('n = ', n)\n",
|
||||
"\n",
|
||||
"# range_n = range(1, n+1)\n",
|
||||
"range_n = list(range(0, n))\n",
|
||||
"\n",
|
||||
"N = n * n\n",
|
||||
"range_N = list(range(1, N + 1))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# x[i,j,k] = 1 means that cell (i,j) contains integer k\n",
|
||||
"x = {}\n",
|
||||
"for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" for k in range_N:\n",
|
||||
" x[i, j, k] = solver.IntVar(0, 1, 'x[%i,%i,%i]' % (i, j, k))\n",
|
||||
"\n",
|
||||
"# For output. Much slower....\n",
|
||||
"if use_output_matrix == 1:\n",
|
||||
" print('Using an output matrix')\n",
|
||||
" square = {}\n",
|
||||
" for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" square[i, j] = solver.IntVar(1, n * n, 'square[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"# the magic sum\n",
|
||||
"s = solver.IntVar(1, n * n * n, 's')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# each cell must be assigned exactly one integer\n",
|
||||
"for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" solver.Add(solver.Sum([x[i, j, k] for k in range_N]) == 1)\n",
|
||||
"\n",
|
||||
"# each integer must be assigned exactly to one cell\n",
|
||||
"for k in range_N:\n",
|
||||
" solver.Add(solver.Sum([x[i, j, k] for i in range_n for j in range_n]) == 1)\n",
|
||||
"\n",
|
||||
"# # the sum in each row must be the magic sum\n",
|
||||
"for i in range_n:\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([k * x[i, j, k] for j in range_n for k in range_N]) == s)\n",
|
||||
"\n",
|
||||
"# # the sum in each column must be the magic sum\n",
|
||||
"for j in range_n:\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([k * x[i, j, k] for i in range_n for k in range_N]) == s)\n",
|
||||
"\n",
|
||||
"# # the sum in the diagonal must be the magic sum\n",
|
||||
"solver.Add(\n",
|
||||
" solver.Sum([k * x[i, i, k] for i in range_n for k in range_N]) == s)\n",
|
||||
"\n",
|
||||
"# # the sum in the co-diagonal must be the magic sum\n",
|
||||
"if range_n[0] == 1:\n",
|
||||
" # for range_n = 1..n\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([k * x[i, n - i + 1, k]\n",
|
||||
" for i in range_n\n",
|
||||
" for k in range_N]) == s)\n",
|
||||
"else:\n",
|
||||
" # for range_n = 0..n-1\n",
|
||||
" solver.Add(\n",
|
||||
" solver.Sum([k * x[i, n - i - 1, k]\n",
|
||||
" for i in range_n\n",
|
||||
" for k in range_N]) == s)\n",
|
||||
"\n",
|
||||
"# for output\n",
|
||||
"if use_output_matrix == 1:\n",
|
||||
" for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" solver.Add(\n",
|
||||
" square[i, j] == solver.Sum([k * x[i, j, k] for k in range_N]))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solver.Solve()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"print('s: ', int(s.SolutionValue()))\n",
|
||||
"if use_output_matrix == 1:\n",
|
||||
" for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" print(int(square[i, j].SolutionValue()), end=' ')\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"else:\n",
|
||||
" for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" print(\n",
|
||||
" sum([int(k * x[i, j, k].SolutionValue()) for k in range_N]),\n",
|
||||
" ' ',\n",
|
||||
" end=' ')\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('\\nx:')\n",
|
||||
"for i in range_n:\n",
|
||||
" for j in range_n:\n",
|
||||
" for k in range_N:\n",
|
||||
" print(int(x[i, j, k].SolutionValue()), end=' ')\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('walltime :', solver.WallTime(), 'ms')\n",
|
||||
"if sol == 'CBC':\n",
|
||||
" print('iterations:', solver.Iterations())\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
115
examples/notebook/contrib/map.ipynb
Normal file
115
examples/notebook/contrib/map.ipynb
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Map coloring problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" From Pascal Van Hentenryck 'The OPL Optimization Programming Language',\n",
|
||||
" page 7, 42.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * Comet: http://www.hakank.org/comet/map.co\n",
|
||||
" * Tailor/Essence': http://hakank.org/tailor/map_coloring.eprime\n",
|
||||
" * SICStus: http://hakank.org/sicstus/map_coloring.pl\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/map.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/map.cpp\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/map.mzn\n",
|
||||
" * Zinc: http://hakank.org/minizinc/map.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Map coloring\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"Belgium = 0\n",
|
||||
"Denmark = 1\n",
|
||||
"France = 2\n",
|
||||
"Germany = 3\n",
|
||||
"Netherlands = 4\n",
|
||||
"Luxembourg = 5\n",
|
||||
"\n",
|
||||
"n = 6\n",
|
||||
"max_num_colors = 4\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"color = [solver.IntVar(1, max_num_colors, \"x%i\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(color[Belgium] == 1) # Symmetry breaking\n",
|
||||
"solver.Add(color[France] != color[Belgium])\n",
|
||||
"solver.Add(color[France] != color[Luxembourg])\n",
|
||||
"solver.Add(color[France] != color[Germany])\n",
|
||||
"solver.Add(color[Luxembourg] != color[Germany])\n",
|
||||
"solver.Add(color[Luxembourg] != color[Belgium])\n",
|
||||
"solver.Add(color[Belgium] != color[Netherlands])\n",
|
||||
"solver.Add(color[Belgium] != color[Germany])\n",
|
||||
"solver.Add(color[Germany] != color[Netherlands])\n",
|
||||
"solver.Add(color[Germany] != color[Denmark])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([color[i] for i in range(n)])\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"# collector = solver.FirstSolutionCollector(solution)\n",
|
||||
"# search_log = solver.SearchLog(100, x[0])\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase([color[i] for i in range(n)], solver.INT_VAR_SIMPLE,\n",
|
||||
" solver.ASSIGN_MIN_VALUE), [collector])\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"print(\"num_solutions: \", num_solutions)\n",
|
||||
"if num_solutions > 0:\n",
|
||||
" for s in range(num_solutions):\n",
|
||||
" colorval = [collector.Value(s, color[i]) for i in range(n)]\n",
|
||||
" print(\"color:\", colorval)\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(\"num_solutions:\", num_solutions)\n",
|
||||
" print(\"failures:\", solver.Failures())\n",
|
||||
" print(\"branches:\", solver.Branches())\n",
|
||||
" print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"else:\n",
|
||||
" print(\"No solutions found\")\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
145
examples/notebook/contrib/marathon2.ipynb
Normal file
145
examples/notebook/contrib/marathon2.ipynb
Normal file
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Marathon puzzle in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Xpress example\n",
|
||||
" http://www.dashoptimization.com/home/cgi-bin/example.pl?id=mosel_puzzle_5_3\n",
|
||||
" '''\n",
|
||||
" Dominique, Ignace, Naren, Olivier, Philippe, and Pascal\n",
|
||||
" have arrived as the first six at the Paris marathon.\n",
|
||||
" Reconstruct their arrival order from the following\n",
|
||||
" information:\n",
|
||||
" a) Olivier has not arrived last\n",
|
||||
" b) Dominique, Pascal and Ignace have arrived before Naren\n",
|
||||
" and Olivier\n",
|
||||
" c) Dominique who was third last year has improved this year.\n",
|
||||
" d) Philippe is among the first four.\n",
|
||||
" e) Ignace has arrived neither in second nor third position.\n",
|
||||
" f) Pascal has beaten Naren by three positions.\n",
|
||||
" g) Neither Ignace nor Dominique are on the fourth position.\n",
|
||||
"\n",
|
||||
" (c) 2002 Dash Associates\n",
|
||||
" author: S. Heipcke, Mar. 2002\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/marathon2.mzn\n",
|
||||
" * SICStus Prolog: http://www.hakank.org/sicstus/marathon2.pl\n",
|
||||
" * ECLiPSe: http://hakank.org/eclipse/marathon2.ecl\n",
|
||||
" * Gecode: http://hakank.org/gecode/marathon2.cpp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Marathon')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 6\n",
|
||||
"\n",
|
||||
"runners_str = [\n",
|
||||
" 'Dominique', 'Ignace', 'Naren', 'Olivier', 'Philippe', 'Pascal'\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"runners = [solver.IntVar(1, n, 'runners[%i]' % i) for i in range(n)]\n",
|
||||
"Dominique, Ignace, Naren, Olivier, Philippe, Pascal = runners\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(runners))\n",
|
||||
"\n",
|
||||
"# a: Olivier not last\n",
|
||||
"solver.Add(Olivier != n)\n",
|
||||
"\n",
|
||||
"# b: Dominique, Pascal and Ignace before Naren and Olivier\n",
|
||||
"solver.Add(Dominique < Naren)\n",
|
||||
"solver.Add(Dominique < Olivier)\n",
|
||||
"solver.Add(Pascal < Naren)\n",
|
||||
"solver.Add(Pascal < Olivier)\n",
|
||||
"solver.Add(Ignace < Naren)\n",
|
||||
"solver.Add(Ignace < Olivier)\n",
|
||||
"\n",
|
||||
"# c: Dominique better than third\n",
|
||||
"solver.Add(Dominique < 3)\n",
|
||||
"\n",
|
||||
"# d: Philippe is among the first four\n",
|
||||
"solver.Add(Philippe <= 4)\n",
|
||||
"\n",
|
||||
"# e: Ignace neither second nor third\n",
|
||||
"solver.Add(Ignace != 2)\n",
|
||||
"solver.Add(Ignace != 3)\n",
|
||||
"\n",
|
||||
"# f: Pascal three places earlier than Naren\n",
|
||||
"solver.Add(Pascal + 3 == Naren)\n",
|
||||
"\n",
|
||||
"# g: Neither Ignace nor Dominique on fourth position\n",
|
||||
"solver.Add(Ignace != 4)\n",
|
||||
"solver.Add(Dominique != 4)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(runners, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n",
|
||||
" solver.ASSIGN_CENTER_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" runners_val = [runners[i].Value() for i in range(n)]\n",
|
||||
" print('runners:', runners_val)\n",
|
||||
" print('Places:')\n",
|
||||
" for i in range(1, n + 1):\n",
|
||||
" for j in range(n):\n",
|
||||
" if runners_val[j] == i:\n",
|
||||
" print('%i: %s' % (i, runners_str[j]))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
131
examples/notebook/contrib/max_flow_taha.ipynb
Normal file
131
examples/notebook/contrib/max_flow_taha.ipynb
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Max flow problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Taha 'Introduction to Operations Research', Example 6.4-2\n",
|
||||
"\n",
|
||||
" Translated from the AMPL code at\n",
|
||||
" http://taha.ineg.uark.edu/maxflo.txt\n",
|
||||
"\n",
|
||||
" Compare with the following model:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/max_flow_taha.mzn\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Max flow problem, Taha')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 5\n",
|
||||
"start = 0\n",
|
||||
"end = n - 1\n",
|
||||
"\n",
|
||||
"nodes = list(range(n))\n",
|
||||
"\n",
|
||||
"# cost matrix\n",
|
||||
"c = [[0, 20, 30, 10, 0], [0, 0, 40, 0, 30], [0, 0, 0, 10, 20],\n",
|
||||
" [0, 0, 5, 0, 20], [0, 0, 0, 0, 0]]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = {}\n",
|
||||
"for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" x[i, j] = solver.IntVar(0, c[i][j], 'x[%i,%i]' % (i, j))\n",
|
||||
"\n",
|
||||
"x_flat = [x[i, j] for i in nodes for j in nodes]\n",
|
||||
"out_flow = [solver.IntVar(0, 10000, 'out_flow[%i]' % i) for i in nodes]\n",
|
||||
"in_flow = [solver.IntVar(0, 10000, 'in_flow[%i]' % i) for i in nodes]\n",
|
||||
"\n",
|
||||
"total = solver.IntVar(0, 10000, 'z')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"cost_sum = solver.Sum([x[start, j] for j in nodes if c[start][j] > 0])\n",
|
||||
"solver.Add(total == cost_sum)\n",
|
||||
"\n",
|
||||
"for i in nodes:\n",
|
||||
" in_flow_sum = solver.Sum([x[j, i] for j in nodes if c[j][i] > 0])\n",
|
||||
" solver.Add(in_flow[i] == in_flow_sum)\n",
|
||||
"\n",
|
||||
" out_flow_sum = solver.Sum([x[i, j] for j in nodes if c[i][j] > 0])\n",
|
||||
" solver.Add(out_flow[i] == out_flow_sum)\n",
|
||||
"\n",
|
||||
"# in_flow == out_flow\n",
|
||||
"for i in nodes:\n",
|
||||
" if i != start and i != end:\n",
|
||||
" solver.Add(out_flow[i] - in_flow[i] == 0)\n",
|
||||
"\n",
|
||||
"s1 = [x[i, start] for i in nodes if c[i][start] > 0]\n",
|
||||
"if len(s1) > 0:\n",
|
||||
" solver.Add(solver.Sum([x[i, start] for i in nodes if c[i][start] > 0] == 0))\n",
|
||||
"\n",
|
||||
"s2 = [x[end, j] for j in nodes if c[end][j] > 0]\n",
|
||||
"if len(s2) > 0:\n",
|
||||
" solver.Add(solver.Sum([x[end, j] for j in nodes if c[end][j] > 0]) == 0)\n",
|
||||
"\n",
|
||||
"# objective: maximize total cost\n",
|
||||
"objective = solver.Maximize(total, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x_flat, solver.INT_VAR_DEFAULT, solver.ASSIGN_MAX_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('total:', total.Value())\n",
|
||||
" print('in_flow:', [in_flow[i].Value() for i in nodes])\n",
|
||||
" print('out_flow:', [out_flow[i].Value() for i in nodes])\n",
|
||||
" for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" print('%2i' % x[i, j].Value(), end=' ')\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
149
examples/notebook/contrib/max_flow_winston1.ipynb
Normal file
149
examples/notebook/contrib/max_flow_winston1.ipynb
Normal file
@@ -0,0 +1,149 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Max flow problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From Winston 'Operations Research', page 420f, 423f\n",
|
||||
" Sunco Oil example.\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/max_flow_winston1.mzn\n",
|
||||
" * Comet: http://hakank.org/comet/max_flow_winston1.co\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Max flow problem, Winston')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 5\n",
|
||||
"nodes = list(range(n))\n",
|
||||
"\n",
|
||||
"# the arcs\n",
|
||||
"# Note:\n",
|
||||
"# This is 1-based to be compatible with other\n",
|
||||
"# implementations.\n",
|
||||
"arcs1 = [[1, 2], [1, 3], [2, 3], [2, 4], [3, 5], [4, 5], [5, 1]]\n",
|
||||
"\n",
|
||||
"# convert arcs to 0-based\n",
|
||||
"arcs = []\n",
|
||||
"for (a_from, a_to) in arcs1:\n",
|
||||
" a_from -= 1\n",
|
||||
" a_to -= 1\n",
|
||||
" arcs.append([a_from, a_to])\n",
|
||||
"\n",
|
||||
"num_arcs = len(arcs)\n",
|
||||
"\n",
|
||||
"# capacities\n",
|
||||
"cap = [2, 3, 3, 4, 2, 1, 100]\n",
|
||||
"\n",
|
||||
"# convert arcs to matrix\n",
|
||||
"# for sanity checking below\n",
|
||||
"mat = {}\n",
|
||||
"for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" c = 0\n",
|
||||
" for k in range(num_arcs):\n",
|
||||
" if arcs[k][0] == i and arcs[k][1] == j:\n",
|
||||
" c = 1\n",
|
||||
" mat[i, j] = c\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"flow = {}\n",
|
||||
"for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" flow[i, j] = solver.IntVar(0, 200, 'flow %i %i' % (i, j))\n",
|
||||
"\n",
|
||||
"flow_flat = [flow[i, j] for i in nodes for j in nodes]\n",
|
||||
"\n",
|
||||
"z = solver.IntVar(0, 10000, 'z')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(z == flow[n - 1, 0])\n",
|
||||
"\n",
|
||||
"# capacity of arcs\n",
|
||||
"for i in range(num_arcs):\n",
|
||||
" solver.Add(flow[arcs[i][0], arcs[i][1]] <= cap[i])\n",
|
||||
"\n",
|
||||
"# inflows == outflows\n",
|
||||
"for i in nodes:\n",
|
||||
" s1 = solver.Sum([\n",
|
||||
" flow[arcs[k][0], arcs[k][1]] for k in range(num_arcs) if arcs[k][1] == i\n",
|
||||
" ])\n",
|
||||
" s2 = solver.Sum([\n",
|
||||
" flow[arcs[k][0], arcs[k][1]] for k in range(num_arcs) if arcs[k][0] == i\n",
|
||||
" ])\n",
|
||||
" solver.Add(s1 == s2)\n",
|
||||
"\n",
|
||||
"# sanity: just arcs with connections can have a flow\n",
|
||||
"for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" if mat[i, j] == 0:\n",
|
||||
" solver.Add(flow[i, j] == 0)\n",
|
||||
"\n",
|
||||
"# objective: maximize z\n",
|
||||
"objective = solver.Maximize(z, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(flow_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db, [objective])\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('z:', z.Value())\n",
|
||||
" for i in nodes:\n",
|
||||
" for j in nodes:\n",
|
||||
" print(flow[i, j].Value(), end=' ')\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
235
examples/notebook/contrib/minesweeper.ipynb
Normal file
235
examples/notebook/contrib/minesweeper.ipynb
Normal file
@@ -0,0 +1,235 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Minesweeper in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From gecode/examples/minesweeper.cc:\n",
|
||||
" '''\n",
|
||||
" A specification is a square matrix of characters. Alphanumeric\n",
|
||||
" characters represent the number of mines adjacent to that field.\n",
|
||||
" Dots represent fields with an unknown number of mines adjacent to\n",
|
||||
" it (or an actual mine).\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" E.g.\n",
|
||||
" '..2.3.'\n",
|
||||
" '2.....'\n",
|
||||
" '..24.3'\n",
|
||||
" '1.34..'\n",
|
||||
" '.....3'\n",
|
||||
" '.3.3..'\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Also see:\n",
|
||||
" * http://www.janko.at/Raetsel/Minesweeper/index.htm\n",
|
||||
"\n",
|
||||
" * http://en.wikipedia.org/wiki/Minesweeper_(computer_game)\n",
|
||||
"\n",
|
||||
" * Ian Stewart on Minesweeper:\n",
|
||||
" http://www.claymath.org/Popular_Lectures/Minesweeper/\n",
|
||||
"\n",
|
||||
" * Richard Kaye's Minesweeper Pages\n",
|
||||
" http://web.mat.bham.ac.uk/R.W.Kaye/minesw/minesw.htm\n",
|
||||
"\n",
|
||||
" * Some Minesweeper Configurations\n",
|
||||
" http://web.mat.bham.ac.uk/R.W.Kaye/minesw/minesw.pdf\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/minesweeper.mzn\n",
|
||||
" * Choco : http://www.hakank.org/choco/MineSweeper.java\n",
|
||||
" * JaCoP : http://www.hakank.org/JaCoP/MineSweeper.java\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/minesweeper.rb\n",
|
||||
" * Comet : http://www.hakank.org/comet/minesweeper.co\n",
|
||||
" * ECLiPSe : http://www.hakank.org/eclipse/minesweeper.ecl\n",
|
||||
" * SICStus : http://www.hakank.org/sicstus/minesweeper.pl\n",
|
||||
" * Tailor/Essence': http://www.hakank.org/tailor/minesweeper.eprime\n",
|
||||
" * Zinc: http://www.hakank.org/minizinc/minesweeper.zinc\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"default_r = 8\n",
|
||||
"default_c = 8\n",
|
||||
"X = -1\n",
|
||||
"default_game = [[2, 3, X, 2, 2, X, 2, 1], [X, X, 4, X, X, 4, X, 2],\n",
|
||||
" [X, X, X, X, X, X, 4, X], [X, 5, X, 6, X, X, X, 2],\n",
|
||||
" [2, X, X, X, 5, 5, X, 2], [1, 3, 4, X, X, X, 4, X],\n",
|
||||
" [0, 1, X, 4, X, X, X, 3], [0, 1, 2, X, 2, 3, X, 2]]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Minesweeper\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# Set default problem\n",
|
||||
"if game == \"\":\n",
|
||||
" game = default_game\n",
|
||||
" r = default_r\n",
|
||||
" c = default_c\n",
|
||||
"else:\n",
|
||||
" print(\"rows:\", r, \" cols:\", c)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Default problem from \"Some Minesweeper Configurations\",page 3\n",
|
||||
"# (same as problem instance minesweeper_config3.txt)\n",
|
||||
"# It has 4 solutions\n",
|
||||
"#\n",
|
||||
"# r = 8\n",
|
||||
"# c = 8\n",
|
||||
"# X = -1\n",
|
||||
"# game = [\n",
|
||||
"# [2,3,X,2,2,X,2,1],\n",
|
||||
"# [X,X,4,X,X,4,X,2],\n",
|
||||
"# [X,X,X,X,X,X,4,X],\n",
|
||||
"# [X,5,X,6,X,X,X,2],\n",
|
||||
"# [2,X,X,X,5,5,X,2],\n",
|
||||
"# [1,3,4,X,X,X,4,X],\n",
|
||||
"# [0,1,X,4,X,X,X,3],\n",
|
||||
"# [0,1,2,X,2,3,X,2]\n",
|
||||
"# ]\n",
|
||||
"\n",
|
||||
"S = [-1, 0, 1] # for the neighbors of \"this\" cell\n",
|
||||
"\n",
|
||||
"# print problem instance\n",
|
||||
"print(\"Problem:\")\n",
|
||||
"for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" if game[i][j] == X:\n",
|
||||
" print(\"X\", end=\" \")\n",
|
||||
" else:\n",
|
||||
" print(game[i][j], end=\" \")\n",
|
||||
" print()\n",
|
||||
"print()\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"mines = {}\n",
|
||||
"for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" mines[(i, j)] = solver.IntVar(0, 1, \"mines %i %i\" % (i, j))\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" if game[i][j] >= 0:\n",
|
||||
" solver.Add(mines[i, j] == 0)\n",
|
||||
" # this cell is the sum of all the surrounding cells\n",
|
||||
" solver.Add(game[i][j] == solver.Sum([\n",
|
||||
" mines[i + a, j + b]\n",
|
||||
" for a in S\n",
|
||||
" for b in S\n",
|
||||
" if i + a >= 0 and j + b >= 0 and i + a < r and j + b < c\n",
|
||||
" ]))\n",
|
||||
" if game[i][j] > X:\n",
|
||||
" # This cell cannot be a mine\n",
|
||||
" solver.Add(mines[i, j] == 0)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([mines[(i, j)] for i in range(r) for j in range(c)])\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase([mines[(i, j)] for i in range(r) for j in range(c)],\n",
|
||||
" solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE), [collector])\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"print(\"num_solutions: \", num_solutions)\n",
|
||||
"if num_solutions > 0:\n",
|
||||
" for s in range(num_solutions):\n",
|
||||
" minesval = [\n",
|
||||
" collector.Value(s, mines[(i, j)]) for i in range(r) for j in range(c)\n",
|
||||
" ]\n",
|
||||
" for i in range(r):\n",
|
||||
" for j in range(c):\n",
|
||||
" print(minesval[i * c + j], end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(\"num_solutions:\", num_solutions)\n",
|
||||
" print(\"failures:\", solver.Failures())\n",
|
||||
" print(\"branches:\", solver.Branches())\n",
|
||||
" print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"else:\n",
|
||||
" print(\"No solutions found\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Read a problem instance from a file\n",
|
||||
"#def read_problem(file):\n",
|
||||
" f = open(file, \"r\")\n",
|
||||
" rows = int(f.readline())\n",
|
||||
" cols = int(f.readline())\n",
|
||||
" game = []\n",
|
||||
" for i in range(rows):\n",
|
||||
" x = f.readline()\n",
|
||||
" row = [0] * cols\n",
|
||||
" for j in range(cols):\n",
|
||||
" if x[j] == \".\":\n",
|
||||
" tmp = -1\n",
|
||||
" else:\n",
|
||||
" tmp = int(x[j])\n",
|
||||
" row[j] = tmp\n",
|
||||
" game.append(row)\n",
|
||||
" return [game, rows, cols]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Print the mines\n",
|
||||
"#\n",
|
||||
"def print_mines(mines, rows, cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(mines[i, j], end=\" \")\n",
|
||||
" print(\"\")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def print_game(game, rows, cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" print(game[i][j], end=\" \")\n",
|
||||
" print(\"\")\n",
|
||||
"\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
131
examples/notebook/contrib/mr_smith.ipynb
Normal file
131
examples/notebook/contrib/mr_smith.ipynb
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Mr Smith in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From an IF Prolog example (http://www.ifcomputer.de/)\n",
|
||||
" '''\n",
|
||||
" The Smith family and their three children want to pay a visit but they\n",
|
||||
" do not all have the time to do so. Following are few hints who will go\n",
|
||||
" and who will not:\n",
|
||||
" o If Mr Smith comes, his wife will come too.\n",
|
||||
" o At least one of their two sons Matt and John will come.\n",
|
||||
" o Either Mrs Smith or Tim will come, but not both.\n",
|
||||
" o Either Tim and John will come, or neither will come.\n",
|
||||
" o If Matt comes, then John and his father will\n",
|
||||
" also come.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" The answer should be:\n",
|
||||
" Mr_Smith_comes = 0\n",
|
||||
" Mrs_Smith_comes = 0\n",
|
||||
" Matt_comes = 0\n",
|
||||
" John_comes = 1\n",
|
||||
" Tim_comes = 1\n",
|
||||
"\n",
|
||||
" Compare with the following models:\n",
|
||||
" * ECLiPSe: http://www.hakank.org/eclipse/mr_smith.ecl\n",
|
||||
" * SICStus Prolog: http://www.hakank.org/sicstus/mr_smith.pl\n",
|
||||
" * Gecode: http://www.hakank.org/gecode/mr_smith.cpp\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/mr_smith.mzn\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Mr Smith problem')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"n = 5\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"x = [solver.IntVar(0, 1, 'x[%i]' % i) for i in range(n)]\n",
|
||||
"Mr_Smith, Mrs_Smith, Matt, John, Tim = x\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# I've kept the MiniZinc constraints for clarity\n",
|
||||
"# and debugging.\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# If Mr Smith comes then his wife will come too.\n",
|
||||
"# (Mr_Smith -> Mrs_Smith)\n",
|
||||
"solver.Add(Mr_Smith - Mrs_Smith <= 0)\n",
|
||||
"\n",
|
||||
"# At least one of their two sons Matt and John will come.\n",
|
||||
"# (Matt \\/ John)\n",
|
||||
"solver.Add(Matt + John >= 1)\n",
|
||||
"\n",
|
||||
"# Either Mrs Smith or Tim will come but not both.\n",
|
||||
"# bool2int(Mrs_Smith) + bool2int(Tim) = 1 /\\\n",
|
||||
"# (Mrs_Smith xor Tim)\n",
|
||||
"solver.Add(Mrs_Smith + Tim == 1)\n",
|
||||
"\n",
|
||||
"# Either Tim and John will come or neither will come.\n",
|
||||
"# (Tim = John)\n",
|
||||
"solver.Add(Tim == John)\n",
|
||||
"\n",
|
||||
"# If Matt comes /\\ then John and his father will also come.\n",
|
||||
"# (Matt -> (John /\\ Mr_Smith))\n",
|
||||
"solver.Add(Matt - (John * Mr_Smith) <= 0)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" num_solutions += 1\n",
|
||||
" print('x:', [x[i].Value() for i in range(n)])\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
209
examples/notebook/contrib/nonogram_default_search.ipynb
Normal file
209
examples/notebook/contrib/nonogram_default_search.ipynb
Normal file
@@ -0,0 +1,209 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com, lperron@google.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Nonogram (Painting by numbers) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Nonogram\n",
|
||||
" '''\n",
|
||||
" Nonograms or Paint by Numbers are picture logic puzzles in which cells in a\n",
|
||||
" grid have to be colored or left blank according to numbers given at the\n",
|
||||
" side of the grid to reveal a hidden picture. In this puzzle type, the\n",
|
||||
" numbers measure how many unbroken lines of filled-in squares there are\n",
|
||||
" in any given row or column. For example, a clue of '4 8 3' would mean\n",
|
||||
" there are sets of four, eight, and three filled squares, in that order,\n",
|
||||
" with at least one blank square between successive groups.\n",
|
||||
"\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" See problem 12 at http://www.csplib.org/.\n",
|
||||
"\n",
|
||||
" http://www.puzzlemuseum.com/nonogram.htm\n",
|
||||
"\n",
|
||||
" Haskell solution:\n",
|
||||
" http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"\n",
|
||||
" Brunetti, Sara & Daurat, Alain (2003)\n",
|
||||
" 'An algorithm reconstructing convex lattice sets'\n",
|
||||
" http://geodisi.u-strasbg.fr/~daurat/papiers/tomoqconv.pdf\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Make a transition (automaton) list of tuples from a\n",
|
||||
"# single pattern, e.g. [3,2,1]\n",
|
||||
"#\n",
|
||||
"def make_transition_tuples(pattern):\n",
|
||||
" p_len = len(pattern)\n",
|
||||
" num_states = p_len + sum(pattern)\n",
|
||||
"\n",
|
||||
" tuples = []\n",
|
||||
"\n",
|
||||
" # this is for handling 0-clues. It generates\n",
|
||||
" # just the minimal state\n",
|
||||
" if num_states == 0:\n",
|
||||
" tuples.append((1, 0, 1))\n",
|
||||
" return (tuples, 1)\n",
|
||||
"\n",
|
||||
" # convert pattern to a 0/1 pattern for easy handling of\n",
|
||||
" # the states\n",
|
||||
" tmp = [0]\n",
|
||||
" c = 0\n",
|
||||
" for pattern_index in range(p_len):\n",
|
||||
" tmp.extend([1] * pattern[pattern_index])\n",
|
||||
" tmp.append(0)\n",
|
||||
"\n",
|
||||
" for i in range(num_states):\n",
|
||||
" state = i + 1\n",
|
||||
" if tmp[i] == 0:\n",
|
||||
" tuples.append((state, 0, state))\n",
|
||||
" tuples.append((state, 1, state + 1))\n",
|
||||
" else:\n",
|
||||
" if i < num_states - 1:\n",
|
||||
" if tmp[i + 1] == 1:\n",
|
||||
" tuples.append((state, 1, state + 1))\n",
|
||||
" else:\n",
|
||||
" tuples.append((state, 0, state + 1))\n",
|
||||
" tuples.append((num_states, 0, num_states))\n",
|
||||
" return (tuples, num_states)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# check each rule by creating an automaton and transition constraint.\n",
|
||||
"#\n",
|
||||
"def check_rule(rules, y):\n",
|
||||
" cleaned_rule = [rules[i] for i in range(len(rules)) if rules[i] > 0]\n",
|
||||
" (transition_tuples, last_state) = make_transition_tuples(cleaned_rule)\n",
|
||||
"\n",
|
||||
" initial_state = 1\n",
|
||||
" accepting_states = [last_state]\n",
|
||||
"\n",
|
||||
" solver = y[0].solver()\n",
|
||||
" solver.Add(\n",
|
||||
" solver.TransitionConstraint(y, transition_tuples, initial_state,\n",
|
||||
" accepting_states))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Nonogram')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"board = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board[i, j] = solver.IntVar(0, 1, 'board[%i, %i]' % (i, j))\n",
|
||||
"\n",
|
||||
"board_flat = [board[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"# Flattened board for labeling.\n",
|
||||
"# This labeling was inspired by a suggestion from\n",
|
||||
"# Pascal Van Hentenryck about my (hakank's) Comet\n",
|
||||
"# nonogram model.\n",
|
||||
"board_label = []\n",
|
||||
"if rows * row_rule_len < cols * col_rule_len:\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"else:\n",
|
||||
" for j in range(cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" check_rule(row_rules[i], [board[i, j] for j in range(cols)])\n",
|
||||
"\n",
|
||||
"for j in range(cols):\n",
|
||||
" check_rule(col_rules[j], [board[i, j] for i in range(rows)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"parameters = pywrapcp.DefaultPhaseParameters()\n",
|
||||
"parameters.heuristic_period = 200000\n",
|
||||
"\n",
|
||||
"db = solver.DefaultPhase(board_label, parameters)\n",
|
||||
"\n",
|
||||
"print('before solver, wall time = ', solver.WallTime(), 'ms')\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in range(rows):\n",
|
||||
" row = [board[i, j].Value() for j in range(cols)]\n",
|
||||
" row_pres = []\n",
|
||||
" for j in row:\n",
|
||||
" if j == 1:\n",
|
||||
" row_pres.append('#')\n",
|
||||
" else:\n",
|
||||
" row_pres.append(' ')\n",
|
||||
" print(' ', ''.join(row_pres))\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(' ', '-' * cols)\n",
|
||||
"\n",
|
||||
" if num_solutions >= 2:\n",
|
||||
" print('2 solutions is enough...')\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Default problem\n",
|
||||
"#\n",
|
||||
"# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"# The lambda picture\n",
|
||||
"#rows = 12\n",
|
||||
"row_rule_len = 3\n",
|
||||
"row_rules = [[0, 0, 2], [0, 1, 2], [0, 1, 1], [0, 0, 2], [0, 0, 1], [0, 0, 3],\n",
|
||||
" [0, 0, 3], [0, 2, 2], [0, 2, 1], [2, 2, 1], [0, 2, 3], [0, 2, 2]]\n",
|
||||
"\n",
|
||||
"cols = 10\n",
|
||||
"col_rule_len = 2\n",
|
||||
"col_rules = [[2, 1], [1, 3], [2, 4], [3, 4], [0, 4], [0, 3], [0, 3], [0, 3],\n",
|
||||
" [0, 2], [0, 2]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
335
examples/notebook/contrib/nonogram_regular.ipynb
Normal file
335
examples/notebook/contrib/nonogram_regular.ipynb
Normal file
@@ -0,0 +1,335 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Nonogram (Painting by numbers) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Nonogram\n",
|
||||
" '''\n",
|
||||
" Nonograms or Paint by Numbers are picture logic puzzles in which cells in a\n",
|
||||
" grid have to be colored or left blank according to numbers given at the\n",
|
||||
" side of the grid to reveal a hidden picture. In this puzzle type, the\n",
|
||||
" numbers measure how many unbroken lines of filled-in squares there are\n",
|
||||
" in any given row or column. For example, a clue of '4 8 3' would mean\n",
|
||||
" there are sets of four, eight, and three filled squares, in that order,\n",
|
||||
" with at least one blank square between successive groups.\n",
|
||||
"\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" See problem 12 at http://www.csplib.org/.\n",
|
||||
"\n",
|
||||
" http://www.puzzlemuseum.com/nonogram.htm\n",
|
||||
"\n",
|
||||
" Haskell solution:\n",
|
||||
" http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"\n",
|
||||
" Brunetti, Sara & Daurat, Alain (2003)\n",
|
||||
" 'An algorithm reconstructing convex lattice sets'\n",
|
||||
" http://geodisi.u-strasbg.fr/~daurat/papiers/tomoqconv.pdf\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" The Comet model (http://www.hakank.org/comet/nonogram_regular.co)\n",
|
||||
" was a major influence when writing this Google CP solver model.\n",
|
||||
"\n",
|
||||
" I have also blogged about the development of a Nonogram solver in Comet\n",
|
||||
" using the regular constraint.\n",
|
||||
" * 'Comet: Nonogram improved: solving problem P200 from 1:30 minutes\n",
|
||||
" to about 1 second'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/03/comet_nonogram_improved_solvin_1.html\n",
|
||||
"\n",
|
||||
" * 'Comet: regular constraint, a much faster Nonogram with the regular\n",
|
||||
" constraint,\n",
|
||||
" some OPL models, and more'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/02/comet_regular_constraint_a_muc_1.html\n",
|
||||
"\n",
|
||||
" Compare with the other models:\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/nonogram.rb (using 'regexps')\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_regular.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton2.mzn\n",
|
||||
" Note: nonogram_create_automaton2.mzn is the preferred model\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Global constraint regular\n",
|
||||
"#\n",
|
||||
"# This is a translation of MiniZinc's regular constraint (defined in\n",
|
||||
"# lib/zinc/globals.mzn), via the Comet code refered above.\n",
|
||||
"# All comments are from the MiniZinc code.\n",
|
||||
"# '''\n",
|
||||
"# The sequence of values in array 'x' (which must all be in the range 1..S)\n",
|
||||
"# is accepted by the DFA of 'Q' states with input 1..S and transition\n",
|
||||
"# function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
|
||||
"# (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
|
||||
"# 1..Q). We reserve state 0 to be an always failing state.\n",
|
||||
"# '''\n",
|
||||
"#\n",
|
||||
"# x : IntVar array\n",
|
||||
"# Q : number of states\n",
|
||||
"# S : input_max\n",
|
||||
"# d : transition matrix\n",
|
||||
"# q0: initial state\n",
|
||||
"# F : accepting states\n",
|
||||
"def regular(x, Q, S, d, q0, F):\n",
|
||||
"\n",
|
||||
" solver = x[0].solver()\n",
|
||||
"\n",
|
||||
" assert Q > 0, 'regular: \"Q\" must be greater than zero'\n",
|
||||
" assert S > 0, 'regular: \"S\" must be greater than zero'\n",
|
||||
"\n",
|
||||
" # d2 is the same as d, except we add one extra transition for\n",
|
||||
" # each possible input; each extra transition is from state zero\n",
|
||||
" # to state zero. This allows us to continue even if we hit a\n",
|
||||
" # non-accepted input.\n",
|
||||
"\n",
|
||||
" # int d2[0..Q, 1..S]\n",
|
||||
" d2 = []\n",
|
||||
" for i in range(Q + 1):\n",
|
||||
" row = []\n",
|
||||
" for j in range(S):\n",
|
||||
" if i == 0:\n",
|
||||
" row.append(0)\n",
|
||||
" else:\n",
|
||||
" row.append(d[i - 1][j])\n",
|
||||
" d2.append(row)\n",
|
||||
"\n",
|
||||
" d2_flatten = [d2[i][j] for i in range(Q + 1) for j in range(S)]\n",
|
||||
"\n",
|
||||
" # If x has index set m..n, then a[m-1] holds the initial state\n",
|
||||
" # (q0), and a[i+1] holds the state we're in after processing\n",
|
||||
" # x[i]. If a[n] is in F, then we succeed (ie. accept the\n",
|
||||
" # string).\n",
|
||||
" x_range = list(range(0, len(x)))\n",
|
||||
" m = 0\n",
|
||||
" n = len(x)\n",
|
||||
"\n",
|
||||
" a = [solver.IntVar(0, Q + 1, 'a[%i]' % i) for i in range(m, n + 1)]\n",
|
||||
"\n",
|
||||
" # Check that the final state is in F\n",
|
||||
" solver.Add(solver.MemberCt(a[-1], F))\n",
|
||||
" # First state is q0\n",
|
||||
" solver.Add(a[m] == q0)\n",
|
||||
" for i in x_range:\n",
|
||||
" solver.Add(x[i] >= 1)\n",
|
||||
" solver.Add(x[i] <= S)\n",
|
||||
" # Determine a[i+1]: a[i+1] == d2[a[i], x[i]]\n",
|
||||
" solver.Add(\n",
|
||||
" a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Make a transition (automaton) matrix from a\n",
|
||||
"# single pattern, e.g. [3,2,1]\n",
|
||||
"#\n",
|
||||
"def make_transition_matrix(pattern):\n",
|
||||
"\n",
|
||||
" p_len = len(pattern)\n",
|
||||
" num_states = p_len + sum(pattern)\n",
|
||||
"\n",
|
||||
" # this is for handling 0-clues. It generates\n",
|
||||
" # just the state 1,2\n",
|
||||
" if num_states == 0:\n",
|
||||
" num_states = 1\n",
|
||||
"\n",
|
||||
" t_matrix = []\n",
|
||||
" for i in range(num_states):\n",
|
||||
" row = []\n",
|
||||
" for j in range(2):\n",
|
||||
" row.append(0)\n",
|
||||
" t_matrix.append(row)\n",
|
||||
"\n",
|
||||
" # convert pattern to a 0/1 pattern for easy handling of\n",
|
||||
" # the states\n",
|
||||
" tmp = [0 for i in range(num_states)]\n",
|
||||
" c = 0\n",
|
||||
" tmp[c] = 0\n",
|
||||
" for i in range(p_len):\n",
|
||||
" for j in range(pattern[i]):\n",
|
||||
" c += 1\n",
|
||||
" tmp[c] = 1\n",
|
||||
" if c < num_states - 1:\n",
|
||||
" c += 1\n",
|
||||
" tmp[c] = 0\n",
|
||||
"\n",
|
||||
" t_matrix[num_states - 1][0] = num_states\n",
|
||||
" t_matrix[num_states - 1][1] = 0\n",
|
||||
"\n",
|
||||
" for i in range(num_states):\n",
|
||||
" if tmp[i] == 0:\n",
|
||||
" t_matrix[i][0] = i + 1\n",
|
||||
" t_matrix[i][1] = i + 2\n",
|
||||
" else:\n",
|
||||
" if i < num_states - 1:\n",
|
||||
" if tmp[i + 1] == 1:\n",
|
||||
" t_matrix[i][0] = 0\n",
|
||||
" t_matrix[i][1] = i + 2\n",
|
||||
" else:\n",
|
||||
" t_matrix[i][0] = i + 2\n",
|
||||
" t_matrix[i][1] = 0\n",
|
||||
"\n",
|
||||
" # print 'The states:'\n",
|
||||
" # for i in range(num_states):\n",
|
||||
" # for j in range(2):\n",
|
||||
" # print t_matrix[i][j],\n",
|
||||
" # print\n",
|
||||
" # print\n",
|
||||
"\n",
|
||||
" return t_matrix\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# check each rule by creating an automaton\n",
|
||||
"# and regular\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def check_rule(rules, y):\n",
|
||||
" solver = y[0].solver()\n",
|
||||
"\n",
|
||||
" r_len = sum([1 for i in range(len(rules)) if rules[i] > 0])\n",
|
||||
" rules_tmp = []\n",
|
||||
" for i in range(len(rules)):\n",
|
||||
" if rules[i] > 0:\n",
|
||||
" rules_tmp.append(rules[i])\n",
|
||||
"\n",
|
||||
" transition_fn = make_transition_matrix(rules_tmp)\n",
|
||||
" n_states = len(transition_fn)\n",
|
||||
" input_max = 2\n",
|
||||
"\n",
|
||||
" # Note: we cannot use 0 since it's the failing state\n",
|
||||
" initial_state = 1\n",
|
||||
" accepting_states = [n_states] # This is the last state\n",
|
||||
"\n",
|
||||
" regular(y, n_states, input_max, transition_fn, initial_state,\n",
|
||||
" accepting_states)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Regular test')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"board = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board[i, j] = solver.IntVar(1, 2, 'board[%i,%i]' % (i, j))\n",
|
||||
"board_flat = [board[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"# Flattened board for labeling.\n",
|
||||
"# This labeling was inspired by a suggestion from\n",
|
||||
"# Pascal Van Hentenryck about my Comet nonogram model.\n",
|
||||
"board_label = []\n",
|
||||
"if rows * row_rule_len < cols * col_rule_len:\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"else:\n",
|
||||
" for j in range(cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" check_rule([row_rules[i][j] for j in range(row_rule_len)],\n",
|
||||
" [board[i, j] for j in range(cols)])\n",
|
||||
"\n",
|
||||
"for j in range(cols):\n",
|
||||
" check_rule([col_rules[j][k] for k in range(col_rule_len)],\n",
|
||||
" [board[i, j] for i in range(rows)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(board_label, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in range(rows):\n",
|
||||
" row = [board[i, j].Value() - 1 for j in range(cols)]\n",
|
||||
" row_pres = []\n",
|
||||
" for j in row:\n",
|
||||
" if j == 1:\n",
|
||||
" row_pres.append('#')\n",
|
||||
" else:\n",
|
||||
" row_pres.append(' ')\n",
|
||||
" print(' ', ''.join(row_pres))\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(' ', '-' * cols)\n",
|
||||
"\n",
|
||||
" if num_solutions >= 2:\n",
|
||||
" print('2 solutions is enough...')\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Default problem\n",
|
||||
"#\n",
|
||||
"# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"# The lambda picture\n",
|
||||
"#rows = 12\n",
|
||||
"row_rule_len = 3\n",
|
||||
"row_rules = [[0, 0, 2], [0, 1, 2], [0, 1, 1], [0, 0, 2], [0, 0, 1], [0, 0, 3],\n",
|
||||
" [0, 0, 3], [0, 2, 2], [0, 2, 1], [2, 2, 1], [0, 2, 3], [0, 2, 2]]\n",
|
||||
"\n",
|
||||
"cols = 10\n",
|
||||
"col_rule_len = 2\n",
|
||||
"col_rules = [[2, 1], [1, 3], [2, 4], [3, 4], [0, 4], [0, 3], [0, 3], [0, 3],\n",
|
||||
" [0, 2], [0, 2]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
331
examples/notebook/contrib/nonogram_table.ipynb
Normal file
331
examples/notebook/contrib/nonogram_table.ipynb
Normal file
@@ -0,0 +1,331 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Nonogram (Painting by numbers) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Nonogram\n",
|
||||
" '''\n",
|
||||
" Nonograms or Paint by Numbers are picture logic puzzles in which cells in a\n",
|
||||
" grid have to be colored or left blank according to numbers given at the\n",
|
||||
" side of the grid to reveal a hidden picture. In this puzzle type, the\n",
|
||||
" numbers measure how many unbroken lines of filled-in squares there are\n",
|
||||
" in any given row or column. For example, a clue of '4 8 3' would mean\n",
|
||||
" there are sets of four, eight, and three filled squares, in that order,\n",
|
||||
" with at least one blank square between successive groups.\n",
|
||||
"\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" See problem 12 at http://www.csplib.org/.\n",
|
||||
"\n",
|
||||
" http://www.puzzlemuseum.com/nonogram.htm\n",
|
||||
"\n",
|
||||
" Haskell solution:\n",
|
||||
" http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"\n",
|
||||
" Brunetti, Sara & Daurat, Alain (2003)\n",
|
||||
" 'An algorithm reconstructing convex lattice sets'\n",
|
||||
" http://geodisi.u-strasbg.fr/~daurat/papiers/tomoqconv.pdf\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" The Comet model (http://www.hakank.org/comet/nonogram_regular.co)\n",
|
||||
" was a major influence when writing this Google CP solver model.\n",
|
||||
"\n",
|
||||
" I have also blogged about the development of a Nonogram solver in Comet\n",
|
||||
" using the regular constraint.\n",
|
||||
" * 'Comet: Nonogram improved: solving problem P200 from 1:30 minutes\n",
|
||||
" to about 1 second'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/03/comet_nonogram_improved_solvin_1.html\n",
|
||||
"\n",
|
||||
" * 'Comet: regular constraint, a much faster Nonogram with the regular\n",
|
||||
" constraint,\n",
|
||||
" some OPL models, and more'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/02/comet_regular_constraint_a_muc_1.html\n",
|
||||
"\n",
|
||||
" Compare with the other models:\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/nonogram.rb (using 'regexps')\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_regular.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton2.mzn\n",
|
||||
" Note: nonogram_create_automaton2.mzn is the preferred model\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Global constraint regular\n",
|
||||
"#\n",
|
||||
"# This is a translation of MiniZinc's regular constraint (defined in\n",
|
||||
"# lib/zinc/globals.mzn), via the Comet code refered above.\n",
|
||||
"# All comments are from the MiniZinc code.\n",
|
||||
"# '''\n",
|
||||
"# The sequence of values in array 'x' (which must all be in the range 1..S)\n",
|
||||
"# is accepted by the DFA of 'Q' states with input 1..S and transition\n",
|
||||
"# function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'\n",
|
||||
"# (which must be in 1..Q) and accepting states 'F' (which all must be in\n",
|
||||
"# 1..Q). We reserve state 0 to be an always failing state.\n",
|
||||
"# '''\n",
|
||||
"#\n",
|
||||
"# x : IntVar array\n",
|
||||
"# Q : number of states\n",
|
||||
"# S : input_max\n",
|
||||
"# d : transition matrix\n",
|
||||
"# q0: initial state\n",
|
||||
"# F : accepting states\n",
|
||||
"def regular(x, Q, S, d, q0, F):\n",
|
||||
"\n",
|
||||
" solver = x[0].solver()\n",
|
||||
"\n",
|
||||
" assert Q > 0, 'regular: \"Q\" must be greater than zero'\n",
|
||||
" assert S > 0, 'regular: \"S\" must be greater than zero'\n",
|
||||
"\n",
|
||||
" # d2 is the same as d, except we add one extra transition for\n",
|
||||
" # each possible input; each extra transition is from state zero\n",
|
||||
" # to state zero. This allows us to continue even if we hit a\n",
|
||||
" # non-accepted input.\n",
|
||||
"\n",
|
||||
" d2 = []\n",
|
||||
" for i in range(Q + 1):\n",
|
||||
" for j in range(S):\n",
|
||||
" if i == 0:\n",
|
||||
" d2.append((0, j, 0))\n",
|
||||
" else:\n",
|
||||
" d2.append((i, j, d[i - 1][j]))\n",
|
||||
"\n",
|
||||
" # If x has index set m..n, then a[m-1] holds the initial state\n",
|
||||
" # (q0), and a[i+1] holds the state we're in after processing\n",
|
||||
" # x[i]. If a[n] is in F, then we succeed (ie. accept the\n",
|
||||
" # string).\n",
|
||||
" x_range = list(range(0, len(x)))\n",
|
||||
" m = 0\n",
|
||||
" n = len(x)\n",
|
||||
"\n",
|
||||
" a = [solver.IntVar(0, Q + 1, 'a[%i]' % i) for i in range(m, n + 1)]\n",
|
||||
"\n",
|
||||
" # Check that the final state is in F\n",
|
||||
" solver.Add(solver.MemberCt(a[-1], F))\n",
|
||||
" # First state is q0\n",
|
||||
" solver.Add(a[m] == q0)\n",
|
||||
" for i in x_range:\n",
|
||||
" solver.Add(x[i] >= 1)\n",
|
||||
" solver.Add(x[i] <= S)\n",
|
||||
" # Determine a[i+1]: a[i+1] == d2[a[i], x[i]]\n",
|
||||
" solver.Add(solver.AllowedAssignments((a[i], x[i] - 1, a[i + 1]), d2))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Make a transition (automaton) matrix from a\n",
|
||||
"# single pattern, e.g. [3,2,1]\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def make_transition_matrix(pattern):\n",
|
||||
"\n",
|
||||
" p_len = len(pattern)\n",
|
||||
" num_states = p_len + sum(pattern)\n",
|
||||
"\n",
|
||||
" # this is for handling 0-clues. It generates\n",
|
||||
" # just the state 1,2\n",
|
||||
" if num_states == 0:\n",
|
||||
" num_states = 1\n",
|
||||
"\n",
|
||||
" t_matrix = []\n",
|
||||
" for i in range(num_states):\n",
|
||||
" row = []\n",
|
||||
" for j in range(2):\n",
|
||||
" row.append(0)\n",
|
||||
" t_matrix.append(row)\n",
|
||||
"\n",
|
||||
" # convert pattern to a 0/1 pattern for easy handling of\n",
|
||||
" # the states\n",
|
||||
" tmp = [0 for i in range(num_states)]\n",
|
||||
" c = 0\n",
|
||||
" tmp[c] = 0\n",
|
||||
" for i in range(p_len):\n",
|
||||
" for j in range(pattern[i]):\n",
|
||||
" c += 1\n",
|
||||
" tmp[c] = 1\n",
|
||||
" if c < num_states - 1:\n",
|
||||
" c += 1\n",
|
||||
" tmp[c] = 0\n",
|
||||
"\n",
|
||||
" t_matrix[num_states - 1][0] = num_states\n",
|
||||
" t_matrix[num_states - 1][1] = 0\n",
|
||||
"\n",
|
||||
" for i in range(num_states):\n",
|
||||
" if tmp[i] == 0:\n",
|
||||
" t_matrix[i][0] = i + 1\n",
|
||||
" t_matrix[i][1] = i + 2\n",
|
||||
" else:\n",
|
||||
" if i < num_states - 1:\n",
|
||||
" if tmp[i + 1] == 1:\n",
|
||||
" t_matrix[i][0] = 0\n",
|
||||
" t_matrix[i][1] = i + 2\n",
|
||||
" else:\n",
|
||||
" t_matrix[i][0] = i + 2\n",
|
||||
" t_matrix[i][1] = 0\n",
|
||||
"\n",
|
||||
" # print 'The states:'\n",
|
||||
" # for i in range(num_states):\n",
|
||||
" # for j in range(2):\n",
|
||||
" # print t_matrix[i][j],\n",
|
||||
" # print\n",
|
||||
" # print\n",
|
||||
"\n",
|
||||
" return t_matrix\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# check each rule by creating an automaton\n",
|
||||
"# and regular\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def check_rule(rules, y):\n",
|
||||
" solver = y[0].solver()\n",
|
||||
"\n",
|
||||
" r_len = sum([1 for i in range(len(rules)) if rules[i] > 0])\n",
|
||||
" rules_tmp = []\n",
|
||||
" for i in range(len(rules)):\n",
|
||||
" if rules[i] > 0:\n",
|
||||
" rules_tmp.append(rules[i])\n",
|
||||
"\n",
|
||||
" transition_fn = make_transition_matrix(rules_tmp)\n",
|
||||
" n_states = len(transition_fn)\n",
|
||||
" input_max = 2\n",
|
||||
"\n",
|
||||
" # Note: we cannot use 0 since it's the failing state\n",
|
||||
" initial_state = 1\n",
|
||||
" accepting_states = [n_states] # This is the last state\n",
|
||||
"\n",
|
||||
" regular(y, n_states, input_max, transition_fn, initial_state,\n",
|
||||
" accepting_states)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Regular test')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"board = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board[i, j] = solver.IntVar(1, 2, 'board[%i, %i]' % (i, j))\n",
|
||||
"board_flat = [board[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"# Flattened board for labeling.\n",
|
||||
"# This labeling was inspired by a suggestion from\n",
|
||||
"# Pascal Van Hentenryck about my Comet nonogram model.\n",
|
||||
"board_label = []\n",
|
||||
"if rows * row_rule_len < cols * col_rule_len:\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"else:\n",
|
||||
" for j in range(cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" check_rule([row_rules[i][j] for j in range(row_rule_len)],\n",
|
||||
" [board[i, j] for j in range(cols)])\n",
|
||||
"\n",
|
||||
"for j in range(cols):\n",
|
||||
" check_rule([col_rules[j][k] for k in range(col_rule_len)],\n",
|
||||
" [board[i, j] for i in range(rows)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(board_label, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in range(rows):\n",
|
||||
" row = [board[i, j].Value() - 1 for j in range(cols)]\n",
|
||||
" row_pres = []\n",
|
||||
" for j in row:\n",
|
||||
" if j == 1:\n",
|
||||
" row_pres.append('#')\n",
|
||||
" else:\n",
|
||||
" row_pres.append(' ')\n",
|
||||
" print(' ', ''.join(row_pres))\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(' ', '-' * cols)\n",
|
||||
"\n",
|
||||
" if num_solutions >= 2:\n",
|
||||
" print('2 solutions is enough...')\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Default problem\n",
|
||||
"#\n",
|
||||
"# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"# The lambda picture\n",
|
||||
"#rows = 12\n",
|
||||
"row_rule_len = 3\n",
|
||||
"row_rules = [[0, 0, 2], [0, 1, 2], [0, 1, 1], [0, 0, 2], [0, 0, 1], [0, 0, 3],\n",
|
||||
" [0, 0, 3], [0, 2, 2], [0, 2, 1], [2, 2, 1], [0, 2, 3], [0, 2, 2]]\n",
|
||||
"\n",
|
||||
"cols = 10\n",
|
||||
"col_rule_len = 2\n",
|
||||
"col_rules = [[2, 1], [1, 3], [2, 4], [3, 4], [0, 4], [0, 3], [0, 3], [0, 3],\n",
|
||||
" [0, 2], [0, 2]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
231
examples/notebook/contrib/nonogram_table2.ipynb
Normal file
231
examples/notebook/contrib/nonogram_table2.ipynb
Normal file
@@ -0,0 +1,231 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Nonogram (Painting by numbers) in Google CP Solver.\n",
|
||||
"\n",
|
||||
" http://en.wikipedia.org/wiki/Nonogram\n",
|
||||
" '''\n",
|
||||
" Nonograms or Paint by Numbers are picture logic puzzles in which cells in a\n",
|
||||
" grid have to be colored or left blank according to numbers given at the\n",
|
||||
" side of the grid to reveal a hidden picture. In this puzzle type, the\n",
|
||||
" numbers measure how many unbroken lines of filled-in squares there are\n",
|
||||
" in any given row or column. For example, a clue of '4 8 3' would mean\n",
|
||||
" there are sets of four, eight, and three filled squares, in that order,\n",
|
||||
" with at least one blank square between successive groups.\n",
|
||||
"\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" See problem 12 at http://www.csplib.org/.\n",
|
||||
"\n",
|
||||
" http://www.puzzlemuseum.com/nonogram.htm\n",
|
||||
"\n",
|
||||
" Haskell solution:\n",
|
||||
" http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"\n",
|
||||
" Brunetti, Sara & Daurat, Alain (2003)\n",
|
||||
" 'An algorithm reconstructing convex lattice sets'\n",
|
||||
" http://geodisi.u-strasbg.fr/~daurat/papiers/tomoqconv.pdf\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" The Comet model (http://www.hakank.org/comet/nonogram_regular.co)\n",
|
||||
" was a major influence when writing this Google CP solver model.\n",
|
||||
"\n",
|
||||
" I have also blogged about the development of a Nonogram solver in Comet\n",
|
||||
" using the regular constraint.\n",
|
||||
" * 'Comet: Nonogram improved: solving problem P200 from 1:30 minutes\n",
|
||||
" to about 1 second'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/03/comet_nonogram_improved_solvin_1.html\n",
|
||||
"\n",
|
||||
" * 'Comet: regular constraint, a much faster Nonogram with the regular\n",
|
||||
" constraint,\n",
|
||||
" some OPL models, and more'\n",
|
||||
" http://www.hakank.org/constraint_programming_blog/2009/02/comet_regular_constraint_a_muc_1.html\n",
|
||||
"\n",
|
||||
" Compare with the other models:\n",
|
||||
" * Gecode/R: http://www.hakank.org/gecode_r/nonogram.rb (using 'regexps')\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_regular.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton.mzn\n",
|
||||
" * MiniZinc: http://www.hakank.org/minizinc/nonogram_create_automaton2.mzn\n",
|
||||
" Note: nonogram_create_automaton2.mzn is the preferred model\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Make a transition (automaton) list of tuples from a\n",
|
||||
"# single pattern, e.g. [3,2,1]\n",
|
||||
"#\n",
|
||||
"def make_transition_tuples(pattern):\n",
|
||||
" p_len = len(pattern)\n",
|
||||
" num_states = p_len + sum(pattern)\n",
|
||||
"\n",
|
||||
" tuples = []\n",
|
||||
"\n",
|
||||
" # this is for handling 0-clues. It generates\n",
|
||||
" # just the minimal state\n",
|
||||
" if num_states == 0:\n",
|
||||
" tuples.append((1, 0, 1))\n",
|
||||
" return (tuples, 1)\n",
|
||||
"\n",
|
||||
" # convert pattern to a 0/1 pattern for easy handling of\n",
|
||||
" # the states\n",
|
||||
" tmp = [0]\n",
|
||||
" c = 0\n",
|
||||
" for pattern_index in range(p_len):\n",
|
||||
" tmp.extend([1] * pattern[pattern_index])\n",
|
||||
" tmp.append(0)\n",
|
||||
"\n",
|
||||
" for i in range(num_states):\n",
|
||||
" state = i + 1\n",
|
||||
" if tmp[i] == 0:\n",
|
||||
" tuples.append((state, 0, state))\n",
|
||||
" tuples.append((state, 1, state + 1))\n",
|
||||
" else:\n",
|
||||
" if i < num_states - 1:\n",
|
||||
" if tmp[i + 1] == 1:\n",
|
||||
" tuples.append((state, 1, state + 1))\n",
|
||||
" else:\n",
|
||||
" tuples.append((state, 0, state + 1))\n",
|
||||
" tuples.append((num_states, 0, num_states))\n",
|
||||
" return (tuples, num_states)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# check each rule by creating an automaton and transition constraint.\n",
|
||||
"#\n",
|
||||
"def check_rule(rules, y):\n",
|
||||
" cleaned_rule = [rules[i] for i in range(len(rules)) if rules[i] > 0]\n",
|
||||
" (transition_tuples, last_state) = make_transition_tuples(cleaned_rule)\n",
|
||||
"\n",
|
||||
" initial_state = 1\n",
|
||||
" accepting_states = [last_state]\n",
|
||||
"\n",
|
||||
" solver = y[0].solver()\n",
|
||||
" solver.Add(\n",
|
||||
" solver.TransitionConstraint(y, transition_tuples, initial_state,\n",
|
||||
" accepting_states))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver('Regular test')\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# variables\n",
|
||||
"#\n",
|
||||
"board = {}\n",
|
||||
"for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board[i, j] = solver.IntVar(0, 1, 'board[%i, %i]' % (i, j))\n",
|
||||
"board_flat = [board[i, j] for i in range(rows) for j in range(cols)]\n",
|
||||
"\n",
|
||||
"# Flattened board for labeling.\n",
|
||||
"# This labeling was inspired by a suggestion from\n",
|
||||
"# Pascal Van Hentenryck about my Comet nonogram model.\n",
|
||||
"board_label = []\n",
|
||||
"if rows * row_rule_len < cols * col_rule_len:\n",
|
||||
" for i in range(rows):\n",
|
||||
" for j in range(cols):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"else:\n",
|
||||
" for j in range(cols):\n",
|
||||
" for i in range(rows):\n",
|
||||
" board_label.append(board[i, j])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"for i in range(rows):\n",
|
||||
" check_rule(row_rules[i], [board[i, j] for j in range(cols)])\n",
|
||||
"\n",
|
||||
"for j in range(cols):\n",
|
||||
" check_rule(col_rules[j], [board[i, j] for i in range(rows)])\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(board_label, solver.CHOOSE_FIRST_UNBOUND,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"print('before solver, wall time = ', solver.WallTime(), 'ms')\n",
|
||||
"solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print()\n",
|
||||
" num_solutions += 1\n",
|
||||
" for i in range(rows):\n",
|
||||
" row = [board[i, j].Value() for j in range(cols)]\n",
|
||||
" row_pres = []\n",
|
||||
" for j in row:\n",
|
||||
" if j == 1:\n",
|
||||
" row_pres.append('#')\n",
|
||||
" else:\n",
|
||||
" row_pres.append(' ')\n",
|
||||
" print(' ', ''.join(row_pres))\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(' ', '-' * cols)\n",
|
||||
"\n",
|
||||
" if num_solutions >= 2:\n",
|
||||
" print('2 solutions is enough...')\n",
|
||||
" break\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"print()\n",
|
||||
"print('num_solutions:', num_solutions)\n",
|
||||
"print('failures:', solver.Failures())\n",
|
||||
"print('branches:', solver.Branches())\n",
|
||||
"print('WallTime:', solver.WallTime(), 'ms')\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# Default problem\n",
|
||||
"#\n",
|
||||
"# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n",
|
||||
"# The lambda picture\n",
|
||||
"#rows = 12\n",
|
||||
"row_rule_len = 3\n",
|
||||
"row_rules = [[0, 0, 2], [0, 1, 2], [0, 1, 1], [0, 0, 2], [0, 0, 1], [0, 0, 3],\n",
|
||||
" [0, 0, 3], [0, 2, 2], [0, 2, 1], [2, 2, 1], [0, 2, 3], [0, 2, 2]]\n",
|
||||
"\n",
|
||||
"cols = 10\n",
|
||||
"col_rule_len = 2\n",
|
||||
"col_rules = [[2, 1], [1, 3], [2, 4], [3, 4], [0, 4], [0, 3], [0, 3], [0, 3],\n",
|
||||
" [0, 2], [0, 2]]\n",
|
||||
"\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
217
examples/notebook/contrib/nontransitive_dice.ipynb
Normal file
217
examples/notebook/contrib/nontransitive_dice.ipynb
Normal file
@@ -0,0 +1,217 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" Nontransitive dice in Google CP Solver.\n",
|
||||
"\n",
|
||||
" From\n",
|
||||
" http://en.wikipedia.org/wiki/Nontransitive_dice\n",
|
||||
" '''\n",
|
||||
" A set of nontransitive dice is a set of dice for which the relation\n",
|
||||
" 'is more likely to roll a higher number' is not transitive. See also\n",
|
||||
" intransitivity.\n",
|
||||
"\n",
|
||||
" This situation is similar to that in the game Rock, Paper, Scissors,\n",
|
||||
" in which each element has an advantage over one choice and a\n",
|
||||
" disadvantage to the other.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" I start with the 3 dice version\n",
|
||||
" '''\n",
|
||||
" * die A has sides {2,2,4,4,9,9},\n",
|
||||
" * die B has sides {1,1,6,6,8,8}, and\n",
|
||||
" * die C has sides {3,3,5,5,7,7}.\n",
|
||||
" '''\n",
|
||||
"\n",
|
||||
" 3 dice:\n",
|
||||
" Maximum winning: 27\n",
|
||||
" comp: [19, 27, 19]\n",
|
||||
" dice:\n",
|
||||
" [[0, 0, 3, 6, 6, 6],\n",
|
||||
" [2, 5, 5, 5, 5, 5],\n",
|
||||
" [1, 1, 4, 4, 4, 7]]\n",
|
||||
" max_win: 27\n",
|
||||
"\n",
|
||||
" Number of solutions: 1\n",
|
||||
" Nodes: 1649873 Time: 25.94\n",
|
||||
" getFailures: 1649853\n",
|
||||
" getBacktracks: 1649873\n",
|
||||
" getPropags: 98105090\n",
|
||||
"\n",
|
||||
" Max winnings where they are the same: 21\n",
|
||||
" comp: [21, 21, 21]\n",
|
||||
" dice:\n",
|
||||
" [[0, 0, 3, 3, 3, 6],\n",
|
||||
" [2, 2, 2, 2, 2, 5],\n",
|
||||
" [1, 1, 1, 4, 4, 4]]\n",
|
||||
" max_win: 21\n",
|
||||
"\n",
|
||||
" Compare with these models:\n",
|
||||
" * MiniZinc: http://hakank.org/minizinc/nontransitive_dice.mzn\n",
|
||||
" * Comet: http://hakank.org/comet/nontransitive_dice.co\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"Nontransitive dice\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"print(\"number of dice:\", m)\n",
|
||||
"print(\"number of sides:\", n)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# declare variables\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"dice = {}\n",
|
||||
"for i in range(m):\n",
|
||||
" for j in range(n):\n",
|
||||
" dice[(i, j)] = solver.IntVar(1, n * 2, \"dice(%i,%i)\" % (i, j))\n",
|
||||
"dice_flat = [dice[(i, j)] for i in range(m) for j in range(n)]\n",
|
||||
"\n",
|
||||
"comp = {}\n",
|
||||
"for i in range(m):\n",
|
||||
" for j in range(2):\n",
|
||||
" comp[(i, j)] = solver.IntVar(0, n * n, \"comp(%i,%i)\" % (i, j))\n",
|
||||
"comp_flat = [comp[(i, j)] for i in range(m) for j in range(2)]\n",
|
||||
"\n",
|
||||
"# The following variables are for summaries or objectives\n",
|
||||
"gap = [solver.IntVar(0, n * n, \"gap(%i)\" % i) for i in range(m)]\n",
|
||||
"gap_sum = solver.IntVar(0, m * n * n, \"gap_sum\")\n",
|
||||
"\n",
|
||||
"max_val = solver.IntVar(0, n * 2, \"max_val\")\n",
|
||||
"max_win = solver.IntVar(0, n * n, \"max_win\")\n",
|
||||
"\n",
|
||||
"# number of occurrences of each value of the dice\n",
|
||||
"counts = [solver.IntVar(0, n * m, \"counts(%i)\" % i) for i in range(n * 2 + 1)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"\n",
|
||||
"# number of occurrences for each number\n",
|
||||
"solver.Add(solver.Distribute(dice_flat, list(range(n * 2 + 1)), counts))\n",
|
||||
"\n",
|
||||
"solver.Add(max_win == solver.Max(comp_flat))\n",
|
||||
"solver.Add(max_val == solver.Max(dice_flat))\n",
|
||||
"\n",
|
||||
"# order of the number of each die, lowest first\n",
|
||||
"[\n",
|
||||
" solver.Add(dice[(i, j)] <= dice[(i, j + 1)])\n",
|
||||
" for i in range(m)\n",
|
||||
" for j in range(n - 1)\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# nontransitivity\n",
|
||||
"[comp[i, 0] > comp[i, 1] for i in range(m)],\n",
|
||||
"\n",
|
||||
"# probability gap\n",
|
||||
"[solver.Add(gap[i] == comp[i, 0] - comp[i, 1]) for i in range(m)]\n",
|
||||
"[solver.Add(gap[i] > 0) for i in range(m)]\n",
|
||||
"solver.Add(gap_sum == solver.Sum(gap))\n",
|
||||
"\n",
|
||||
"# and now we roll...\n",
|
||||
"# Number of wins for [A vs B, B vs A]\n",
|
||||
"for d in range(m):\n",
|
||||
" b1 = [\n",
|
||||
" solver.IsGreaterVar(dice[d % m, r1], dice[(d + 1) % m, r2])\n",
|
||||
" for r1 in range(n)\n",
|
||||
" for r2 in range(n)\n",
|
||||
" ]\n",
|
||||
" solver.Add(comp[d % m, 0] == solver.Sum(b1))\n",
|
||||
"\n",
|
||||
" b2 = [\n",
|
||||
" solver.IsGreaterVar(dice[(d + 1) % m, r1], dice[d % m, r2])\n",
|
||||
" for r1 in range(n)\n",
|
||||
" for r2 in range(n)\n",
|
||||
" ]\n",
|
||||
" solver.Add(comp[d % m, 1] == solver.Sum(b2))\n",
|
||||
"\n",
|
||||
"# objective\n",
|
||||
"if minimize_val != 0:\n",
|
||||
" print(\"Minimizing max_val\")\n",
|
||||
" objective = solver.Minimize(max_val, 1)\n",
|
||||
" # other experiments\n",
|
||||
" # objective = solver.Maximize(max_win, 1)\n",
|
||||
" # objective = solver.Maximize(gap_sum, 1)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"db = solver.Phase(dice_flat + comp_flat, solver.INT_VAR_DEFAULT,\n",
|
||||
" solver.ASSIGN_MIN_VALUE)\n",
|
||||
"\n",
|
||||
"if minimize_val:\n",
|
||||
" solver.NewSearch(db, [objective])\n",
|
||||
"else:\n",
|
||||
" solver.NewSearch(db)\n",
|
||||
"\n",
|
||||
"num_solutions = 0\n",
|
||||
"while solver.NextSolution():\n",
|
||||
" print(\"gap_sum:\", gap_sum.Value())\n",
|
||||
" print(\"gap:\", [gap[i].Value() for i in range(m)])\n",
|
||||
" print(\"max_val:\", max_val.Value())\n",
|
||||
" print(\"max_win:\", max_win.Value())\n",
|
||||
" print(\"dice:\")\n",
|
||||
" for i in range(m):\n",
|
||||
" for j in range(n):\n",
|
||||
" print(dice[(i, j)].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print(\"comp:\")\n",
|
||||
" for i in range(m):\n",
|
||||
" for j in range(2):\n",
|
||||
" print(comp[(i, j)].Value(), end=\" \")\n",
|
||||
" print()\n",
|
||||
" print(\"counts:\", [counts[i].Value() for i in range(n * 2 + 1)])\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" num_solutions += 1\n",
|
||||
"\n",
|
||||
"solver.EndSearch()\n",
|
||||
"\n",
|
||||
"print()\n",
|
||||
"print(\"num_solutions:\", num_solutions)\n",
|
||||
"print(\"failures:\", solver.Failures())\n",
|
||||
"print(\"branches:\", solver.Branches())\n",
|
||||
"print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"m = 3 # number of dice\n",
|
||||
"n = 6 # number of sides of each die\n",
|
||||
"minimize_val = 0 # Minimizing max value (0: no, 1: yes)\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
108
examples/notebook/contrib/nqueens.ipynb
Normal file
108
examples/notebook/contrib/nqueens.ipynb
Normal file
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010 Hakan Kjellerstrand hakank@gmail.com\n",
|
||||
"#\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",
|
||||
"\n",
|
||||
" n-queens problem in Google CP Solver.\n",
|
||||
"\n",
|
||||
" N queens problem.\n",
|
||||
"\n",
|
||||
" This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n",
|
||||
" Also see my other Google CP Solver models:\n",
|
||||
" http://www.hakank.org/google_or_tools/\n",
|
||||
"\"\"\"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"from ortools.constraint_solver import pywrapcp\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Create the solver.\n",
|
||||
"solver = pywrapcp.Solver(\"n-queens\")\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# data\n",
|
||||
"#\n",
|
||||
"# n = 8 # size of board (n x n)\n",
|
||||
"\n",
|
||||
"# declare variables\n",
|
||||
"q = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(n)]\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# constraints\n",
|
||||
"#\n",
|
||||
"solver.Add(solver.AllDifferent(q))\n",
|
||||
"for i in range(n):\n",
|
||||
" for j in range(i):\n",
|
||||
" solver.Add(q[i] != q[j])\n",
|
||||
" solver.Add(q[i] + i != q[j] + j)\n",
|
||||
" solver.Add(q[i] - i != q[j] - j)\n",
|
||||
"\n",
|
||||
"# for i in range(n):\n",
|
||||
"# for j in range(i):\n",
|
||||
"# solver.Add(abs(q[i]-q[j]) != abs(i-j))\n",
|
||||
"\n",
|
||||
"# symmetry breaking\n",
|
||||
"# solver.Add(q[0] == 0)\n",
|
||||
"\n",
|
||||
"#\n",
|
||||
"# solution and search\n",
|
||||
"#\n",
|
||||
"solution = solver.Assignment()\n",
|
||||
"solution.Add([q[i] for i in range(n)])\n",
|
||||
"\n",
|
||||
"collector = solver.AllSolutionCollector(solution)\n",
|
||||
"# collector = solver.FirstSolutionCollector(solution)\n",
|
||||
"# search_log = solver.SearchLog(100, x[0])\n",
|
||||
"solver.Solve(\n",
|
||||
" solver.Phase([q[i] for i in range(n)], solver.INT_VAR_SIMPLE,\n",
|
||||
" solver.ASSIGN_MIN_VALUE), [collector])\n",
|
||||
"\n",
|
||||
"num_solutions = collector.SolutionCount()\n",
|
||||
"print(\"num_solutions: \", num_solutions)\n",
|
||||
"if num_solutions > 0:\n",
|
||||
" for s in range(num_solutions):\n",
|
||||
" qval = [collector.Value(s, q[i]) for i in range(n)]\n",
|
||||
" print(\"q:\", qval)\n",
|
||||
" for i in range(n):\n",
|
||||
" for j in range(n):\n",
|
||||
" if qval[i] == j:\n",
|
||||
" print(\"Q\", end=\" \")\n",
|
||||
" else:\n",
|
||||
" print(\"_\", end=\" \")\n",
|
||||
" print()\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" print()\n",
|
||||
" print(\"num_solutions:\", num_solutions)\n",
|
||||
" print(\"failures:\", solver.Failures())\n",
|
||||
" print(\"branches:\", solver.Branches())\n",
|
||||
" print(\"WallTime:\", solver.WallTime())\n",
|
||||
"\n",
|
||||
"else:\n",
|
||||
" print(\"No solutions found\")\n",
|
||||
"\n",
|
||||
"n = 8\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user