diff --git a/examples/notebook/algorithms/knapsack.ipynb b/examples/notebook/algorithms/knapsack.ipynb index 80dc92ae26..76e1a70980 100644 --- a/examples/notebook/algorithms/knapsack.ipynb +++ b/examples/notebook/algorithms/knapsack.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "A simple knapsack problem." + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,67 +82,46 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"A simple knapsack problem.\"\"\"\n", - "# [START program]\n", - "# [START import]\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", + "def main():\n", + " # Create the solver.\n", + " solver = pywrapknapsack_solver.KnapsackSolver(\n", + " pywrapknapsack_solver.KnapsackSolver.\n", + " KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, 'KnapsackExample')\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", + " 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", "\n", - "# [START solve]\n", - "solver.Init(values, weights, capacities)\n", - "computed_value = solver.Solve()\n", - "# [END solve]\n", + " solver.Init(values, weights, capacities)\n", + " computed_value = solver.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", + " 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", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/algorithms/simple_knapsack_program.ipynb b/examples/notebook/algorithms/simple_knapsack_program.ipynb index df73119d23..de7cf21d02 100644 --- a/examples/notebook/algorithms/simple_knapsack_program.ipynb +++ b/examples/notebook/algorithms/simple_knapsack_program.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "A simple knapsack problem." + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,57 +82,36 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"A simple knapsack problem.\"\"\"\n", - "# [START import]\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", + "def main():\n", + " # Create the solver.\n", + " solver = pywrapknapsack_solver.KnapsackSolver(\n", + " pywrapknapsack_solver.KnapsackSolver.\n", + " KNAPSACK_DYNAMIC_PROGRAMMING_SOLVER, \"test\")\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", + " 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", "\n", - "# [START solve]\n", - "solver.Init(values, weights, capacities)\n", - "computed_value = solver.Solve()\n", - "# [END solve]\n", + " solver.Init(values, weights, capacities)\n", + " computed_value = solver.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", + " 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", + " print(\"Packed items: \", packed_items)\n", + " print(\"Packed weights: \", packed_weights)\n", + " print(\"Total weight (same as total value): \", computed_value)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/cp_is_fun_cp.ipynb b/examples/notebook/constraint_solver/cp_is_fun_cp.ipynb index 27b36dcb3f..ae4c0d1fa5 100644 --- a/examples/notebook/constraint_solver/cp_is_fun_cp.ipynb +++ b/examples/notebook/constraint_solver/cp_is_fun_cp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,19 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Cryptarithmetic puzzle.\n", + "\n", + "First attempt to solve equation CP + IS + FUN = TRUE\n", + "where each letter represents a unique digit.\n", + "\n", + "This problem has 72 different solutions in base 10.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,85 +87,58 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Cryptarithmetic puzzle.\n", - "\n", - "First attempt to solve equation CP + IS + FUN = TRUE\n", - "where each letter represents a unique digit.\n", - "\n", - "This problem has 72 different solutions in base 10.\n", - "\"\"\"\n", - "# [START import]\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# Constraint programming engine\n", - "# [START solver]\n", - "solver = pywrapcp.Solver('CP is fun!')\n", - "# [END solver]\n", + "def main():\n", + " # Constraint programming engine\n", + " solver = pywrapcp.Solver('CP is fun!')\n", "\n", - "# [START variables]\n", - "base = 10\n", + " base = 10\n", "\n", - "# Decision variables.\n", - "digits = list(range(0, base))\n", - "digits_without_zero = list(range(1, base))\n", - "c = solver.IntVar(digits_without_zero, 'C')\n", - "p = solver.IntVar(digits, 'P')\n", - "i = solver.IntVar(digits_without_zero, 'I')\n", - "s = solver.IntVar(digits, 'S')\n", - "f = solver.IntVar(digits_without_zero, 'F')\n", - "u = solver.IntVar(digits, 'U')\n", - "n = solver.IntVar(digits, 'N')\n", - "t = solver.IntVar(digits_without_zero, 'T')\n", - "r = solver.IntVar(digits, 'R')\n", - "e = solver.IntVar(digits, 'E')\n", + " # Decision variables.\n", + " digits = list(range(0, base))\n", + " digits_without_zero = list(range(1, base))\n", + " c = solver.IntVar(digits_without_zero, 'C')\n", + " p = solver.IntVar(digits, 'P')\n", + " i = solver.IntVar(digits_without_zero, 'I')\n", + " s = solver.IntVar(digits, 'S')\n", + " f = solver.IntVar(digits_without_zero, 'F')\n", + " u = solver.IntVar(digits, 'U')\n", + " n = solver.IntVar(digits, 'N')\n", + " t = solver.IntVar(digits_without_zero, 'T')\n", + " r = solver.IntVar(digits, 'R')\n", + " e = solver.IntVar(digits, 'E')\n", "\n", - "# We need to group variables in a list to use the constraint AllDifferent.\n", - "letters = [c, p, i, s, f, u, n, t, r, e]\n", + " # We need to group variables in a list to use the constraint AllDifferent.\n", + " letters = [c, p, i, s, f, u, n, t, r, e]\n", "\n", - "# Verify that we have enough digits.\n", - "assert base >= len(letters)\n", - "# [END variables]\n", + " # Verify that we have enough digits.\n", + " assert base >= len(letters)\n", "\n", - "# Define constraints.\n", - "# [START constraints]\n", - "solver.Add(solver.AllDifferent(letters))\n", + " # Define constraints.\n", + " solver.Add(solver.AllDifferent(letters))\n", "\n", - "# CP + IS + FUN = TRUE\n", - "solver.Add(p + s + n + base * (c + i + u) + base * base * f == e +\n", - " base * u + base * base * r + base * base * base * t)\n", - "# [END constraints]\n", + " # CP + IS + FUN = TRUE\n", + " solver.Add(p + s + n + base * (c + i + u) + base * base * f == e +\n", + " base * u + base * base * r + base * base * base * t)\n", "\n", - "# [START solve]\n", - "solution_count = 0\n", - "db = solver.Phase(letters, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", - "solver.NewSearch(db)\n", - "while solver.NextSolution():\n", - " print(letters)\n", - " # Is CP + IS + FUN = TRUE?\n", - " assert (base * c.Value() + p.Value() + base * i.Value() + s.Value() +\n", - " base * base * f.Value() + base * u.Value() +\n", - " n.Value() == base * base * base * t.Value() +\n", - " base * base * r.Value() + base * u.Value() + e.Value())\n", - " solution_count += 1\n", - "solver.EndSearch()\n", - "print(f'Number of solutions found: {solution_count}')\n", - "# [END solve]\n", + " solution_count = 0\n", + " db = solver.Phase(letters, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + " solver.NewSearch(db)\n", + " while solver.NextSolution():\n", + " print(letters)\n", + " # Is CP + IS + FUN = TRUE?\n", + " assert (base * c.Value() + p.Value() + base * i.Value() + s.Value() +\n", + " base * base * f.Value() + base * u.Value() +\n", + " n.Value() == base * base * base * t.Value() +\n", + " base * base * r.Value() + base * u.Value() + e.Value())\n", + " solution_count += 1\n", + " solver.EndSearch()\n", + " print(f'Number of solutions found: {solution_count}')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/cvrp.ipynb b/examples/notebook/constraint_solver/cvrp.ipynb index 8ef5cacc8a..739a1d2aa4 100644 --- a/examples/notebook/constraint_solver/cvrp.ipynb +++ b/examples/notebook/constraint_solver/cvrp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,28 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\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", + "Capacitated Vehicle Routing Problem (CVRP).\n", "\n", " This is a sample using the routing library python wrapper to solve a CVRP\n", " problem.\n", @@ -97,9 +80,17 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters.\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from functools import partial\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -234,38 +225,42 @@ "########\n", "# Main #\n", "########\n", - "\"\"\"Entry point of the program\"\"\"\n", - "# Instantiate the data problem.\n", - "data = create_data_model()\n", + "def main():\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", + " # 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", + " # 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", + " # 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", + " # 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", - "search_parameters.local_search_metaheuristic = (\n", - " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", - "search_parameters.time_limit.FromSeconds(1)\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", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(1)\n", "\n", - "# Solve the problem.\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "print_solution(data, routing, manager, assignment)\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\n", + " print_solution(data, routing, manager, assignment)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/cvrp_reload.ipynb b/examples/notebook/constraint_solver/cvrp_reload.ipynb index e58a98e926..80e2e1682e 100644 --- a/examples/notebook/constraint_solver/cvrp_reload.ipynb +++ b/examples/notebook/constraint_solver/cvrp_reload.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,28 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\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", + "Capacitated Vehicle Routing Problem (CVRP).\n", "\n", " This is a sample using the routing library python wrapper to solve a CVRP\n", " problem while allowing multiple trips, i.e., vehicles can return to a depot\n", @@ -116,9 +99,17 @@ " new nodes introduced, to avoid schedules having spurious transits through\n", " those new nodes unless it's necessary to reload. This consideration is taken\n", " into account in `create_distance_evaluator()`.\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from functools import partial\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -415,49 +406,53 @@ "########\n", "# Main #\n", "########\n", - "\"\"\"Entry point of the program\"\"\"\n", - "# Instantiate the data problem.\n", - "data = create_data_model()\n", + "def main():\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", + " # 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", + " # 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", + " # 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, manager, data, distance_evaluator_index)\n", + " # Add Distance constraint to minimize the longuest route\n", + " add_distance_dimension(routing, manager, data, 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", + " # 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", + " # 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", - "search_parameters.local_search_metaheuristic = (\n", - " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", - "search_parameters.time_limit.FromSeconds(3)\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", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(3)\n", "\n", - "# Solve the problem.\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "if solution:\n", - " print_solution(data, manager, routing, solution)\n", - "else:\n", - " print(\"No solution found !\")\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print(\"No solution found !\")\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/cvrptw.ipynb b/examples/notebook/constraint_solver/cvrptw.ipynb index fac014b931..ba2e1ce342 100644 --- a/examples/notebook/constraint_solver/cvrptw.ipynb +++ b/examples/notebook/constraint_solver/cvrptw.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,29 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\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", - "# [START program]\n", - "\"\"\"Capacitated Vehicle Routing Problem with Time Windows (CVRPTW).\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", @@ -98,16 +80,21 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters and time in minutes.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from functools import partial\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", @@ -154,7 +141,6 @@ " data['vehicle_speed'] = 83 # Travel speed: 5km/h converted in m/min\n", " data['depot'] = 0\n", " return data\n", - " # [END data_model]\n", "\n", "\n", "#######################\n", @@ -275,7 +261,6 @@ " #routing.AddToAssignment(time_dimension.SlackVar(self.routing.End(vehicle_id)))\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(manager, routing, assignment): # pylint:disable=too-many-locals\n", " \"\"\"Prints assignment on console\"\"\"\n", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -321,74 +306,57 @@ " print('Total Distance of all routes: {0}m'.format(total_distance))\n", " print('Total Load of all routes: {}'.format(total_load))\n", " print('Total Time of all routes: {0}min'.format(total_time))\n", - " # [END solution_printer]\n", "\n", "\n", - "\"\"\"Solve the Capacitated VRP with time windows.\"\"\"\n", - "# Instantiate the data problem.\n", - "# [START data]\n", - "data = create_data_model()\n", - "# [END data]\n", + "def main():\n", + " \"\"\"Solve the Capacitated VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\n", "\n", - "# Create the routing index manager.\n", - "# [START index_manager]\n", - "manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n", - " data['num_vehicles'], data['depot'])\n", - "# [END index_manager]\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", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", - "# [END routing_model]\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "# Define weight of each edge.\n", - "# [START transit_callback]\n", - "distance_evaluator_index = routing.RegisterTransitCallback(\n", - " partial(create_distance_evaluator(data), manager))\n", - "# [END transit_callback]\n", + " # Define weight of each edge.\n", + " distance_evaluator_index = routing.RegisterTransitCallback(\n", + " partial(create_distance_evaluator(data), manager))\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", "\n", - "# Add Capacity constraint.\n", - "# [START 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", - "# [END capacity_constraint]\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", - "# [START time_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", - "# [END time_constraint]\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", - "# [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.time_limit.FromSeconds(2)\n", - "search_parameters.log_search = True\n", - "# [END parameters]\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)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(2)\n", + " search_parameters.log_search = True\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "else:\n", - " print('No solution found!')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + " else:\n", + " print('No solution found!')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/cvrptw_break.ipynb b/examples/notebook/constraint_solver/cvrptw_break.ipynb index 711be7ff9c..a6e1fefa08 100644 --- a/examples/notebook/constraint_solver/cvrptw_break.ipynb +++ b/examples/notebook/constraint_solver/cvrptw_break.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Capacitated Vehicle Routing Problem with Time Windows (CVRPTW).\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", @@ -96,16 +80,21 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters and time in minutes.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import functools\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", @@ -153,7 +142,6 @@ " data['vehicle_speed'] = 83 # Travel speed: 5km/h converted in m/min\n", " data['depot'] = 0\n", " return data\n", - " # [END data_model]\n", "\n", "\n", "def manhattan_distance(position_1, position_2):\n", @@ -274,7 +262,6 @@ " # be added to the assignment.\n", "\n", "\n", - "# [START solution_printer]\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", @@ -328,75 +315,70 @@ " print('Total Distance of all routes: {0}m'.format(total_distance))\n", " print('Total Load of all routes: {}'.format(total_load))\n", " print('Total Time of all routes: {0}min'.format(total_time))\n", - " # [END solution_printer]\n", "\n", "\n", - "\"\"\"Entry point of the program.\"\"\"\n", - "# Instantiate the data problem.\n", - "# [START data]\n", - "data = create_data_model()\n", - "# [END data]\n", + "def main():\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['numlocations_'],\n", - " data['num_vehicles'], data['depot'])\n", + " # Create the routing index manager\n", + " manager = pywrapcp.RoutingIndexManager(data['numlocations_'],\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create Routing Model\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "# Define weight of each edge\n", - "distance_evaluator_index = routing.RegisterTransitCallback(\n", - " functools.partial(create_distance_evaluator(data), manager))\n", - "routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", + " # Define weight of each edge\n", + " distance_evaluator_index = routing.RegisterTransitCallback(\n", + " functools.partial(create_distance_evaluator(data), manager))\n", + " routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", "\n", - "# Add Capacity constraint\n", - "demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n", - " functools.partial(create_demand_evaluator(data), manager))\n", - "add_capacity_constraints(routing, data, demand_evaluator_index)\n", + " # Add Capacity constraint\n", + " demand_evaluator_index = routing.RegisterUnaryTransitCallback(\n", + " functools.partial(create_demand_evaluator(data), manager))\n", + " add_capacity_constraints(routing, data, demand_evaluator_index)\n", "\n", - "# Add Time Window constraint\n", - "time_evaluator_index = routing.RegisterTransitCallback(\n", - " functools.partial(create_time_evaluator(data), manager))\n", - "add_time_window_constraints(routing, manager, data, time_evaluator_index)\n", + " # Add Time Window constraint\n", + " time_evaluator_index = routing.RegisterTransitCallback(\n", + " functools.partial(create_time_evaluator(data), manager))\n", + " add_time_window_constraints(routing, manager, data, time_evaluator_index)\n", "\n", - "# Add breaks\n", - "time_dimension = routing.GetDimensionOrDie('Time')\n", - "node_visit_transit = {}\n", - "for index in range(routing.Size()):\n", - " node = manager.IndexToNode(index)\n", - " node_visit_transit[index] = int(data['demands'][node] *\n", - " data['time_per_demand_unit'])\n", + " # Add breaks\n", + " time_dimension = routing.GetDimensionOrDie('Time')\n", + " node_visit_transit = {}\n", + " for index in range(routing.Size()):\n", + " node = manager.IndexToNode(index)\n", + " node_visit_transit[index] = int(data['demands'][node] *\n", + " data['time_per_demand_unit'])\n", "\n", - "break_intervals = {}\n", - "for v in range(data['num_vehicles']):\n", - " vehicle_break = data['breaks'][v]\n", - " break_intervals[v] = [\n", - " routing.solver().FixedDurationIntervalVar(15, 100, vehicle_break[0],\n", - " vehicle_break[1],\n", - " f'Break for vehicle {v}')\n", - " ]\n", - " time_dimension.SetBreakIntervalsOfVehicle(break_intervals[v], v,\n", - " node_visit_transit.values())\n", + " break_intervals = {}\n", + " for v in range(data['num_vehicles']):\n", + " vehicle_break = data['breaks'][v]\n", + " break_intervals[v] = [\n", + " routing.solver().FixedDurationIntervalVar(15, 100, vehicle_break[0],\n", + " vehicle_break[1],\n", + " f'Break for vehicle {v}')\n", + " ]\n", + " time_dimension.SetBreakIntervalsOfVehicle(break_intervals[v], v,\n", + " node_visit_transit.values())\n", "\n", - "# Setting first solution heuristic (cheapest addition).\n", - "# [START parameters]\n", - "search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "search_parameters.first_solution_strategy = (\n", - " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n", - "# [END parameters]\n", + " # 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", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if assignment:\n", - " print_solution(data, manager, routing, assignment)\n", - "else:\n", - " print('No solution found!')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(data, manager, routing, assignment)\n", + " else:\n", + " print('No solution found!')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/nqueens_cp.ipynb b/examples/notebook/constraint_solver/nqueens_cp.ipynb index ee7e6e8679..a7a4401b85 100644 --- a/examples/notebook/constraint_solver/nqueens_cp.ipynb +++ b/examples/notebook/constraint_solver/nqueens_cp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "OR-Tools solution to the N-queens problem." + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,82 +82,61 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"OR-Tools solution to the N-queens problem.\"\"\"\n", - "# [START import]\n", "import sys\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# Creates the solver.\n", - "# [START solver]\n", - "solver = pywrapcp.Solver('n-queens')\n", - "# [END solver]\n", + "def main(board_size):\n", + " # Creates the solver.\n", + " solver = pywrapcp.Solver('n-queens')\n", "\n", - "# Creates the variables.\n", - "# [START variables]\n", - "# The array index is the column, and the value is the row.\n", - "queens = [\n", - " solver.IntVar(0, board_size - 1, f'x{i}') for i in range(board_size)\n", - "]\n", - "# [END variables]\n", + " # Creates the variables.\n", + " # The array index is the column, and the value is the row.\n", + " queens = [\n", + " solver.IntVar(0, board_size - 1, f'x{i}') for i in range(board_size)\n", + " ]\n", "\n", - "# Creates the constraints.\n", - "# [START constraints]\n", - "# All rows must be different.\n", - "solver.Add(solver.AllDifferent(queens))\n", + " # Creates the constraints.\n", + " # All rows must be different.\n", + " solver.Add(solver.AllDifferent(queens))\n", "\n", - "# No two queens can be on the same diagonal.\n", - "solver.Add(solver.AllDifferent([queens[i] + i for i in range(board_size)]))\n", - "solver.Add(solver.AllDifferent([queens[i] - i for i in range(board_size)]))\n", - "# [END constraints]\n", + " # No two queens can be on the same diagonal.\n", + " solver.Add(solver.AllDifferent([queens[i] + i for i in range(board_size)]))\n", + " solver.Add(solver.AllDifferent([queens[i] - i for i in range(board_size)]))\n", "\n", - "# [START db]\n", - "db = solver.Phase(queens, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE)\n", - "# [END db]\n", + " db = solver.Phase(queens, solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE)\n", "\n", - "# [START solve]\n", - "# Iterates through the solutions, displaying each.\n", - "num_solutions = 0\n", - "solver.NewSearch(db)\n", - "while solver.NextSolution():\n", - " # Displays the solution just computed.\n", - " for i in range(board_size):\n", - " for j in range(board_size):\n", - " if queens[j].Value() == i:\n", - " # There is a queen in column j, row i.\n", - " print('Q', end=' ')\n", - " else:\n", - " print('_', end=' ')\n", + " # Iterates through the solutions, displaying each.\n", + " num_solutions = 0\n", + " solver.NewSearch(db)\n", + " while solver.NextSolution():\n", + " # Displays the solution just computed.\n", + " for i in range(board_size):\n", + " for j in range(board_size):\n", + " if queens[j].Value() == i:\n", + " # There is a queen in column j, row i.\n", + " print('Q', end=' ')\n", + " else:\n", + " print('_', end=' ')\n", + " print()\n", " print()\n", - " print()\n", - " num_solutions += 1\n", - "solver.EndSearch()\n", - "# [END solve]\n", + " num_solutions += 1\n", + " solver.EndSearch()\n", "\n", - "# Statistics.\n", - "# [START statistics]\n", - "print('\\nStatistics')\n", - "print(f' failures: {solver.Failures()}')\n", - "print(f' branches: {solver.Branches()}')\n", - "print(f' wall time: {solver.WallTime()} ms')\n", - "print(f' Solutions found: {num_solutions}')\n", - "# [END statistics]\n", + " # Statistics.\n", + " print('\\nStatistics')\n", + " print(f' failures: {solver.Failures()}')\n", + " print(f' branches: {solver.Branches()}')\n", + " print(f' wall time: {solver.WallTime()} ms')\n", + " print(f' Solutions found: {num_solutions}')\n", + "\n", + "\n", + "# By default, solve the 8x8 problem.\n", + "size = 8\n", + "if len(sys.argv) > 1:\n", + " size = int(sys.argv[1])\n", + "main(size)\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/simple_cp_program.ipynb b/examples/notebook/constraint_solver/simple_cp_program.ipynb index acf973b2fd..8fc5d5379f 100644 --- a/examples/notebook/constraint_solver/simple_cp_program.ipynb +++ b/examples/notebook/constraint_solver/simple_cp_program.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Constraint optimization example.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,72 +82,46 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Constraint optimization example.\"\"\"\n", - "\n", - "# [START import]\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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the solver.\n", + " solver = pywrapcp.Solver('CPSimple')\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", + " # Create the 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", "\n", - "# Constraint 0: x != y.\n", - "# [START constraints]\n", - "solver.Add(x != y)\n", - "print('Number of constraints: ', solver.Constraints())\n", - "# [END constraints]\n", + " # Constraint 0: x != y.\n", + " solver.Add(x != y)\n", + " print('Number of constraints: ', solver.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", + " # Solve the problem.\n", + " decision_builder = solver.Phase([x, y, z], solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE)\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", + " # Print solution on console.\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", "\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", + " print('Advanced usage:')\n", + " print('Problem solved in ', solver.WallTime(), 'ms')\n", + " print('Memory usage: ', pywrapcp.Solver.MemoryUsage(), 'bytes')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/simple_routing_program.ipynb b/examples/notebook/constraint_solver/simple_routing_program.ipynb index 2586e78082..48b7b9dcab 100644 --- a/examples/notebook/constraint_solver/simple_routing_program.ipynb +++ b/examples/notebook/constraint_solver/simple_routing_program.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicle Routing example.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,91 +82,61 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicle Routing example.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "\"\"\"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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " num_locations = 5\n", + " num_vehicles = 1\n", + " depot = 0\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot)\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a 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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC) # pylint: disable=no-member\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\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", + " # Print solution 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", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/tsp.ipynb b/examples/notebook/constraint_solver/tsp.ipynb index c69208ad72..c47ecf3f49 100644 --- a/examples/notebook/constraint_solver/tsp.ipynb +++ b/examples/notebook/constraint_solver/tsp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,18 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Travelling Salesman Problem.\n", + "\n", + "A description of the problem can be found here:\n", + "http://en.wikipedia.org/wiki/Travelling_salesperson_problem.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,33 +86,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Travelling Salesman Problem.\n", - "\n", - "A description of the problem can be found here:\n", - "http://en.wikipedia.org/wiki/Travelling_salesperson_problem.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -120,10 +109,8 @@ " 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", @@ -147,10 +134,8 @@ " 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", @@ -165,54 +150,41 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['locations']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", - "# [END routing_model]\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\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", + " # Create and register a transit callback.\n", + " distance_callback = create_distance_callback(data, manager)\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if assignment:\n", - " print_solution(manager, routing, assignment)\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(manager, routing, assignment)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/tsp_circuit_board.ipynb b/examples/notebook/constraint_solver/tsp_circuit_board.ipynb index 0dc48e8892..c3e533304c 100644 --- a/examples/notebook/constraint_solver/tsp_circuit_board.ipynb +++ b/examples/notebook/constraint_solver/tsp_circuit_board.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Travelling Salesperson Problem (TSP) on a circuit board.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,30 +82,11 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Travelling Salesperson Problem (TSP) on a circuit board.\"\"\"\n", - "\n", - "# [START import]\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", @@ -154,10 +143,8 @@ " 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", @@ -172,10 +159,8 @@ " 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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print('Objective: {}'.format(solution.ObjectiveValue()))\n", @@ -190,61 +175,48 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['locations']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", - "# [END routing_model]\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "# [START transit_callback]\n", - "distance_matrix = compute_euclidean_distance_matrix(data['locations'])\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", + " 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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/tsp_cities.ipynb b/examples/notebook/constraint_solver/tsp_cities.ipynb index 1b93bad0e8..5a5bb06739 100644 --- a/examples/notebook/constraint_solver/tsp_cities.ipynb +++ b/examples/notebook/constraint_solver/tsp_cities.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Travelling Salesperson Problem (TSP) between cities.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Travelling Salesperson Problem (TSP) between cities.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -118,10 +107,8 @@ " 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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print('Objective: {} miles'.format(solution.ObjectiveValue()))\n", @@ -136,60 +123,47 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " 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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/tsp_distance_matrix.ipynb b/examples/notebook/constraint_solver/tsp_distance_matrix.ipynb index 263bd55930..abada7d4e6 100644 --- a/examples/notebook/constraint_solver/tsp_distance_matrix.ipynb +++ b/examples/notebook/constraint_solver/tsp_distance_matrix.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Travelling Salesman Problem.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Travelling Salesman Problem.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -173,10 +162,8 @@ " 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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print('Objective: {}'.format(solution.ObjectiveValue()))\n", @@ -191,61 +178,48 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp.ipynb b/examples/notebook/constraint_solver/vrp.ipynb index 7e54c00810..89ad8fc2fc 100644 --- a/examples/notebook/constraint_solver/vrp.ipynb +++ b/examples/notebook/constraint_solver/vrp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Vehicles Routing Problem (VRP).\n", + "Simple Vehicles Routing Problem (VRP).\n", "\n", " This is a sample using the routing library python wrapper to solve a VRP\n", " problem.\n", @@ -96,15 +80,20 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "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", @@ -181,10 +170,8 @@ " 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", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -205,63 +192,50 @@ " total_distance += route_distance\n", " print('Total Distance of all routes: {}m'.format(total_distance))\n", "\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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(data, manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_breaks.ipynb b/examples/notebook/constraint_solver/vrp_breaks.ipynb index 4664f84ec5..2bb568662b 100644 --- a/examples/notebook/constraint_solver/vrp_breaks.ipynb +++ b/examples/notebook/constraint_solver/vrp_breaks.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicle Routing Problem (VRP) with breaks.\n", + "Vehicle Routing Problem (VRP) with breaks.\n", "\n", " This is a sample using the routing library python wrapper to solve a VRP\n", " problem.\n", @@ -96,15 +80,20 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Durations are in minutes.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "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", @@ -134,10 +123,8 @@ " data['service_time'][data['depot']] = 0\n", " assert len(data['time_matrix']) == len(data['service_time'])\n", " return data\n", - " # [END data_model]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(manager, routing, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -169,103 +156,88 @@ " print(plan_output)\n", " total_time += solution.Value(time_var)\n", " print(f'Total time of all routes: {total_time}min')\n", - " # [END solution_printer]\n", "\n", "\n", - "\"\"\"Solve the VRP with time windows.\"\"\"\n", - "# Instantiate the data problem.\n", - "# [START data]\n", - "data = create_data_model()\n", - "# [END data]\n", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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 + service time between the two nodes.\"\"\"\n", - " # Convert from routing variable Index to time matrix NodeIndex.\n", - " from_node = manager.IndexToNode(from_index)\n", - " to_node = manager.IndexToNode(to_index)\n", - " return data['time_matrix'][from_node][to_node] + data['service_time'][\n", - " from_node]\n", + " # Create and register a transit callback.\n", + " def time_callback(from_index, to_index):\n", + " \"\"\"Returns the travel time + service time between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to time matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['time_matrix'][from_node][to_node] + data['service_time'][\n", + " from_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", "\n", - "# Add Time Windows constraint.\n", - "time = 'Time'\n", - "routing.AddDimension(\n", - " transit_callback_index,\n", - " 10, # needed optional waiting time to place break\n", - " 180, # maximum time per vehicle\n", - " True, # Force start cumul to zero.\n", - " time)\n", - "time_dimension = routing.GetDimensionOrDie(time)\n", - "time_dimension.SetGlobalSpanCostCoefficient(10)\n", + " # Add Time Windows constraint.\n", + " time = 'Time'\n", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 10, # needed optional waiting time to place break\n", + " 180, # maximum time per vehicle\n", + " True, # Force start cumul to zero.\n", + " time)\n", + " time_dimension = routing.GetDimensionOrDie(time)\n", + " time_dimension.SetGlobalSpanCostCoefficient(10)\n", "\n", - "# Breaks\n", - "# [START break_constraint]\n", - "# warning: Need a pre-travel array using the solver's index order.\n", - "node_visit_transit = [0] * routing.Size()\n", - "for index in range(routing.Size()):\n", - " node = manager.IndexToNode(index)\n", - " node_visit_transit[index] = data['service_time'][node]\n", + " # Breaks\n", + " # warning: Need a pre-travel array using the solver's index order.\n", + " node_visit_transit = [0] * routing.Size()\n", + " for index in range(routing.Size()):\n", + " node = manager.IndexToNode(index)\n", + " node_visit_transit[index] = data['service_time'][node]\n", "\n", - "break_intervals = {}\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " break_intervals[v] = [\n", - " routing.solver().FixedDurationIntervalVar(\n", - " 50, # start min\n", - " 60, # start max\n", - " 10, # duration: 10 min\n", - " False, # optional: no\n", - " f'Break for vehicle {v}')\n", - " ]\n", - " time_dimension.SetBreakIntervalsOfVehicle(\n", - " break_intervals[v], # breaks\n", - " v, # vehicle index\n", - " node_visit_transit)\n", - "# [END break_constraint]\n", + " break_intervals = {}\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " break_intervals[v] = [\n", + " routing.solver().FixedDurationIntervalVar(\n", + " 50, # start min\n", + " 60, # start max\n", + " 10, # duration: 10 min\n", + " False, # optional: no\n", + " f'Break for vehicle {v}')\n", + " ]\n", + " time_dimension.SetBreakIntervalsOfVehicle(\n", + " break_intervals[v], # breaks\n", + " v, # vehicle index\n", + " node_visit_transit)\n", "\n", - "# Setting first solution heuristic.\n", - "# [START parameters]\n", - "search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "search_parameters.first_solution_strategy = (\n", - " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", - "search_parameters.local_search_metaheuristic = (\n", - " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", - "# search_parameters.log_search = True\n", - "search_parameters.time_limit.FromSeconds(2)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " # search_parameters.log_search = True\n", + " search_parameters.time_limit.FromSeconds(2)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_breaks_from_start.ipynb b/examples/notebook/constraint_solver/vrp_breaks_from_start.ipynb index c7993d1308..82294b75c6 100644 --- a/examples/notebook/constraint_solver/vrp_breaks_from_start.ipynb +++ b/examples/notebook/constraint_solver/vrp_breaks_from_start.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP) with breaks relative to the vehicle start time.\n", + "Vehicles Routing Problem (VRP) with breaks relative to the vehicle start time.\n", " Each vehicles start at T:15min, T:30min, T:45min and T:60min respectively.\n", "\n", " Each vehicle must perform a break lasting 5 minutes,\n", @@ -97,15 +81,20 @@ " between [45+25,45+45] i.e. in the range [70, 90].\n", "\n", " Durations are in minutes.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "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", @@ -135,10 +124,8 @@ " data['service_time'][data['depot']] = 0\n", " assert len(data['time_matrix']) == len(data['service_time'])\n", " return data\n", - " # [END data_model]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(manager, routing, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -173,105 +160,90 @@ " print(f'Time of the route: {route_time}min\\n')\n", " total_time += route_time\n", " print(f'Total time of all routes: {total_time}min')\n", - " # [END solution_printer]\n", "\n", "\n", - "\"\"\"Solve the VRP with time windows.\"\"\"\n", - "# Instantiate the data problem.\n", - "# [START data]\n", - "data = create_data_model()\n", - "# [END data]\n", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\n", "\n", - "# Create the routing index manager.\n", - "# [START index_manager]\n", - "manager = pywrapcp.RoutingIndexManager(\n", - " len(data['time_matrix']),\n", - " data['num_vehicles'],\n", - " data['depot'])\n", - "# [END index_manager]\n", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(\n", + " len(data['time_matrix']),\n", + " data['num_vehicles'],\n", + " data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", - "# [END routing_model]\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\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", + " # Create and register a 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", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", "\n", - "# Add Time Windows constraint.\n", - "time = 'Time'\n", - "routing.AddDimension(\n", - " transit_callback_index,\n", - " 10, # need optional waiting time to place break\n", - " 180, # maximum time per vehicle\n", - " False, # Don't force start cumul to zero.\n", - " time)\n", - "time_dimension = routing.GetDimensionOrDie(time)\n", - "time_dimension.SetGlobalSpanCostCoefficient(10)\n", + " # Add Time Windows constraint.\n", + " time = 'Time'\n", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 10, # need optional waiting time to place break\n", + " 180, # maximum time per vehicle\n", + " False, # Don't force start cumul to zero.\n", + " time)\n", + " time_dimension = routing.GetDimensionOrDie(time)\n", + " time_dimension.SetGlobalSpanCostCoefficient(10)\n", "\n", - "# Each vehicle start with a 15min delay\n", - "for vehicle_id in range(manager.GetNumberOfVehicles()):\n", - " index = routing.Start(vehicle_id)\n", - " time_dimension.CumulVar(index).SetValue((vehicle_id + 1) * 15)\n", + " # Each vehicle start with a 15min delay\n", + " for vehicle_id in range(manager.GetNumberOfVehicles()):\n", + " index = routing.Start(vehicle_id)\n", + " time_dimension.CumulVar(index).SetValue((vehicle_id + 1) * 15)\n", "\n", - "# Add breaks\n", - "# [START break_constraint]\n", - "# warning: Need a pre-travel array using the solver's index order.\n", - "node_visit_transit = [0] * routing.Size()\n", - "for index in range(routing.Size()):\n", - " node = manager.IndexToNode(index)\n", - " node_visit_transit[index] = data['service_time'][node]\n", + " # Add breaks\n", + " # warning: Need a pre-travel array using the solver's index order.\n", + " node_visit_transit = [0] * routing.Size()\n", + " for index in range(routing.Size()):\n", + " node = manager.IndexToNode(index)\n", + " node_visit_transit[index] = data['service_time'][node]\n", "\n", - "# Add a break lasting 5 minutes, start between 25 and 45 minutes after route start\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " start_var = time_dimension.CumulVar(routing.Start(v))\n", - " break_start = routing.solver().Sum([routing.solver().IntVar(25, 45), start_var])\n", + " # Add a break lasting 5 minutes, start between 25 and 45 minutes after route start\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " start_var = time_dimension.CumulVar(routing.Start(v))\n", + " break_start = routing.solver().Sum([routing.solver().IntVar(25, 45), start_var])\n", "\n", - " break_intervals = [\n", - " routing.solver().FixedDurationIntervalVar(\n", - " break_start, 5, 'Break for vehicle {}'.format(v))\n", - " ]\n", - " time_dimension.SetBreakIntervalsOfVehicle(break_intervals, v, node_visit_transit)\n", - "# [END break_constraint]\n", + " break_intervals = [\n", + " routing.solver().FixedDurationIntervalVar(\n", + " break_start, 5, 'Break for vehicle {}'.format(v))\n", + " ]\n", + " time_dimension.SetBreakIntervalsOfVehicle(break_intervals, v, node_visit_transit)\n", "\n", - "# Setting first solution heuristic.\n", - "# [START parameters]\n", - "search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "search_parameters.first_solution_strategy = (\n", - " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", - "search_parameters.local_search_metaheuristic = (\n", - " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", - "# search_parameters.log_search = True\n", - "search_parameters.time_limit.FromSeconds(2)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " # search_parameters.log_search = True\n", + " search_parameters.time_limit.FromSeconds(2)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_capacity.ipynb b/examples/notebook/constraint_solver/vrp_capacity.ipynb index e34d4880e7..1b73061f21 100644 --- a/examples/notebook/constraint_solver/vrp_capacity.ipynb +++ b/examples/notebook/constraint_solver/vrp_capacity.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Capacited Vehicles Routing Problem (CVRP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Capacited Vehicles Routing Problem (CVRP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -170,17 +159,13 @@ " 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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -208,83 +193,68 @@ " 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", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", + " # Define cost of each arc.\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", + " # Add 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", + " 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", "\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.time_limit.FromSeconds(1)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(1)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_drop_nodes.ipynb b/examples/notebook/constraint_solver/vrp_drop_nodes.ipynb index ca21831c62..0353098f13 100644 --- a/examples/notebook/constraint_solver/vrp_drop_nodes.ipynb +++ b/examples/notebook/constraint_solver/vrp_drop_nodes.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Capacited Vehicles Routing Problem (CVRP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Capacited Vehicles Routing Problem (CVRP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -170,17 +159,13 @@ " 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", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -217,87 +202,72 @@ " 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", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", + " # Define cost of each arc.\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", + " # Add 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", + " 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", "\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.time_limit.FromSeconds(1)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(1)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(data, manager, routing, assignment)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_global_span.ipynb b/examples/notebook/constraint_solver/vrp_global_span.ipynb index 5d46922ece..65e3a74bef 100644 --- a/examples/notebook/constraint_solver/vrp_global_span.ipynb +++ b/examples/notebook/constraint_solver/vrp_global_span.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Vehicles Routing Problem (VRP).\n", + "Simple Vehicles Routing Problem (VRP).\n", "\n", " This is a sample using the routing library python wrapper to solve a VRP\n", " problem.\n", @@ -96,15 +80,20 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "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", @@ -181,10 +170,8 @@ " 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", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -205,76 +192,61 @@ " max_route_distance = max(route_distance, max_route_distance)\n", " print('Maximum of the route distances: {}m'.format(max_route_distance))\n", "\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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(data, manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_initial_routes.ipynb b/examples/notebook/constraint_solver/vrp_initial_routes.ipynb index 6498e2f842..8958dc65a0 100644 --- a/examples/notebook/constraint_solver/vrp_initial_routes.ipynb +++ b/examples/notebook/constraint_solver/vrp_initial_routes.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicles Routing Problem (VRP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,28 +82,9 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP).\"\"\"\n", - "\n", - "# [START import]\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", @@ -169,21 +158,17 @@ " 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", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -204,81 +189,64 @@ " max_route_distance = max(route_distance, max_route_distance)\n", " print('Maximum of the route distances: {}m'.format(max_route_distance))\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", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " initial_solution = routing.ReadAssignmentFromRoutes(data['initial_routes'],\n", + " True)\n", + " print('Initial solution:')\n", + " print_solution(data, manager, routing, initial_solution)\n", "\n", - "# Set default search parameters.\n", - "# [START parameters]\n", - "search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "# [END parameters]\n", + " # Set default search parameters.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveFromAssignmentWithParameters(\n", - " initial_solution, search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveFromAssignmentWithParameters(\n", + " initial_solution, search_parameters)\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", + " # Print solution on console.\n", + " if solution:\n", + " print('Solution after search:')\n", + " print_solution(data, manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_node_max.ipynb b/examples/notebook/constraint_solver/vrp_node_max.ipynb index ccde33d905..e1a51f3bc1 100644 --- a/examples/notebook/constraint_solver/vrp_node_max.ipynb +++ b/examples/notebook/constraint_solver/vrp_node_max.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,18 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicles Routing Problem (VRP).\n", + "\n", + "Each route as an associated objective cost equal to the max node value along the\n", + "road multiply by a constant factor (4200)\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,33 +86,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP).\n", - "\n", - "Each route as an associated objective cost equal to the max node value along the\n", - "road multiply by a constant factor (4200)\n", - "\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -198,10 +187,8 @@ " data['depot'] = 0\n", " return data\n", "\n", - "# [END data_model]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(data, manager, routing, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -236,148 +223,133 @@ " max_route_distance = max(route_distance, max_route_distance)\n", " print('Maximum of the route distances: {}m'.format(max_route_distance))\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", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", - " 3_000, # vehicle maximum travel distance\n", - " True, # start cumul to zero\n", - " dimension_name)\n", - "distance_dimension = routing.GetDimensionOrDie(dimension_name)\n", - "distance_dimension.SetGlobalSpanCostCoefficient(10)\n", - "# [END distance_constraint]\n", + " # Add Distance constraint.\n", + " dimension_name = 'Distance'\n", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 0, # no slack\n", + " 3_000, # vehicle maximum travel distance\n", + " True, # start cumul to zero\n", + " dimension_name)\n", + " distance_dimension = routing.GetDimensionOrDie(dimension_name)\n", + " distance_dimension.SetGlobalSpanCostCoefficient(10)\n", "\n", - "# Max Node value Constraint.\n", - "# Dimension One will be used to compute the max node value up to the node in\n", - "# the route and store the result in the SlackVar of the node.\n", - "routing.AddConstantDimensionWithSlack(\n", - " 0, # transit 0\n", - " 42 * 16, # capacity: be able to store PEAK*ROUTE_LENGTH in worst case\n", - " 42, # slack_max: to be able to store peak in slack\n", - " True, # Fix StartCumulToZero not really matter here\n", - " 'One')\n", - "dim_one = routing.GetDimensionOrDie('One')\n", + " # Max Node value Constraint.\n", + " # Dimension One will be used to compute the max node value up to the node in\n", + " # the route and store the result in the SlackVar of the node.\n", + " routing.AddConstantDimensionWithSlack(\n", + " 0, # transit 0\n", + " 42 * 16, # capacity: be able to store PEAK*ROUTE_LENGTH in worst case\n", + " 42, # slack_max: to be able to store peak in slack\n", + " True, # Fix StartCumulToZero not really matter here\n", + " 'One')\n", + " dim_one = routing.GetDimensionOrDie('One')\n", "\n", - "# Dimension Two will be used to store the max node value in the route end node\n", - "# CumulVar so we can use it as an objective cost.\n", - "routing.AddConstantDimensionWithSlack(\n", - " 0, # transit 0\n", - " 42 * 16, # capacity: be able to have PEAK value in CumulVar(End)\n", - " 42, # slack_max: to be able to store peak in slack\n", - " True, # Fix StartCumulToZero YES here\n", - " 'Two')\n", - "dim_two = routing.GetDimensionOrDie('Two')\n", + " # Dimension Two will be used to store the max node value in the route end node\n", + " # CumulVar so we can use it as an objective cost.\n", + " routing.AddConstantDimensionWithSlack(\n", + " 0, # transit 0\n", + " 42 * 16, # capacity: be able to have PEAK value in CumulVar(End)\n", + " 42, # slack_max: to be able to store peak in slack\n", + " True, # Fix StartCumulToZero YES here\n", + " 'Two')\n", + " dim_two = routing.GetDimensionOrDie('Two')\n", "\n", - "# force depot Slack to be value since we don't have any predecessor...\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " start = routing.Start(v)\n", - " dim_one.SlackVar(start).SetValue(data['value'][0])\n", - " routing.AddToAssignment(dim_one.SlackVar(start))\n", - "\n", - " dim_two.SlackVar(start).SetValue(data['value'][0])\n", - " routing.AddToAssignment(dim_two.SlackVar(start))\n", - "\n", - "# Step by step relation\n", - "# Slack(N) = max( Slack(N-1) , value(N) )\n", - "solver = routing.solver()\n", - "for node in range(1, 17):\n", - " index = manager.NodeToIndex(node)\n", - " routing.AddToAssignment(dim_one.SlackVar(index))\n", - " routing.AddToAssignment(dim_two.SlackVar(index))\n", - " test = []\n", + " # force depot Slack to be value since we don't have any predecessor...\n", " for v in range(manager.GetNumberOfVehicles()):\n", - " previous_index = routing.Start(v)\n", - " cond = routing.NextVar(previous_index) == index\n", - " value = solver.Max(dim_one.SlackVar(previous_index),\n", - " data['value'][node])\n", - " test.append((cond * value).Var())\n", - " for previous in range(1, 17):\n", - " previous_index = manager.NodeToIndex(previous)\n", - " cond = routing.NextVar(previous_index) == index\n", - " value = solver.Max(dim_one.SlackVar(previous_index),\n", - " data['value'][node])\n", - " test.append((cond * value).Var())\n", - " solver.Add(solver.Sum(test) == dim_one.SlackVar(index))\n", + " start = routing.Start(v)\n", + " dim_one.SlackVar(start).SetValue(data['value'][0])\n", + " routing.AddToAssignment(dim_one.SlackVar(start))\n", "\n", - "# relation between dimensions, copy last node Slack from dim ONE to dim TWO\n", - "for node in range(1, 17):\n", - " index = manager.NodeToIndex(node)\n", - " values = []\n", + " dim_two.SlackVar(start).SetValue(data['value'][0])\n", + " routing.AddToAssignment(dim_two.SlackVar(start))\n", + "\n", + " # Step by step relation\n", + " # Slack(N) = max( Slack(N-1) , value(N) )\n", + " solver = routing.solver()\n", + " for node in range(1, 17):\n", + " index = manager.NodeToIndex(node)\n", + " routing.AddToAssignment(dim_one.SlackVar(index))\n", + " routing.AddToAssignment(dim_two.SlackVar(index))\n", + " test = []\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " previous_index = routing.Start(v)\n", + " cond = routing.NextVar(previous_index) == index\n", + " value = solver.Max(dim_one.SlackVar(previous_index),\n", + " data['value'][node])\n", + " test.append((cond * value).Var())\n", + " for previous in range(1, 17):\n", + " previous_index = manager.NodeToIndex(previous)\n", + " cond = routing.NextVar(previous_index) == index\n", + " value = solver.Max(dim_one.SlackVar(previous_index),\n", + " data['value'][node])\n", + " test.append((cond * value).Var())\n", + " solver.Add(solver.Sum(test) == dim_one.SlackVar(index))\n", + "\n", + " # relation between dimensions, copy last node Slack from dim ONE to dim TWO\n", + " for node in range(1, 17):\n", + " index = manager.NodeToIndex(node)\n", + " values = []\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " next_index = routing.End(v)\n", + " cond = routing.NextVar(index) == next_index\n", + " value = dim_one.SlackVar(index)\n", + " values.append((cond * value).Var())\n", + " solver.Add(solver.Sum(values) == dim_two.SlackVar(index))\n", + "\n", + " # Should force all others dim_two slack var to zero...\n", " for v in range(manager.GetNumberOfVehicles()):\n", - " next_index = routing.End(v)\n", - " cond = routing.NextVar(index) == next_index\n", - " value = dim_one.SlackVar(index)\n", - " values.append((cond * value).Var())\n", - " solver.Add(solver.Sum(values) == dim_two.SlackVar(index))\n", + " end = routing.End(v)\n", + " dim_two.SetCumulVarSoftUpperBound(end, 0, 4200)\n", "\n", - "# Should force all others dim_two slack var to zero...\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " end = routing.End(v)\n", - " dim_two.SetCumulVarSoftUpperBound(end, 0, 4200)\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " # search_parameters.log_search = True\n", + " search_parameters.time_limit.FromSeconds(5)\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(5)\n", - "# [END parameters]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(data, manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_nodes_indices.ipynb b/examples/notebook/constraint_solver/vrp_nodes_indices.ipynb index 7926cb85d7..2e3417fa7c 100644 --- a/examples/notebook/constraint_solver/vrp_nodes_indices.ipynb +++ b/examples/notebook/constraint_solver/vrp_nodes_indices.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Sample to better understand Node/Index relation.\n", + "Sample to better understand Node/Index relation.\n", "\n", "This script generate few markdown tables to better understand\n", "the relation between nodes and indices.\n", @@ -110,64 +94,76 @@ "* Allways use routing.Start(), routing.End(), manager.IndexToNode() or manager.NodeToIndex().\n", "* Location node is not necessarily equal to its index.\n", "* To loop through ALL indices use manager.GetNumberOfIndices() (Python) or manager::num_indices() (C++)\n", - "\"\"\"\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "\"\"\"Entry point of the program.\"\"\"\n", - "locations = 17\n", - "starts = [5, 5, 7, 8]\n", - "ends = [1, 2, 4, 4]\n", - "vehicles = len(starts)\n", - "assert len(starts) == len(ends)\n", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " locations = 17\n", + " starts = [5, 5, 7, 8]\n", + " ends = [1, 2, 4, 4]\n", + " vehicles = len(starts)\n", + " assert len(starts) == len(ends)\n", "\n", - "manager = pywrapcp.RoutingIndexManager(locations, vehicles, starts, ends)\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " manager = pywrapcp.RoutingIndexManager(locations, vehicles, starts, ends)\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "print('Starts/Ends:')\n", - "header = '| |'\n", - "separator = '|---|'\n", - "v_starts = '| start |'\n", - "v_ends = '| end |'\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " header += f' vehicle {v} |'\n", - " separator += '---|'\n", - " v_starts += f' {starts[v]} |'\n", - " v_ends += f' {ends[v]} |'\n", - "print(header)\n", - "print(separator)\n", - "print(v_starts)\n", - "print(v_ends)\n", + " print('Starts/Ends:')\n", + " header = '| |'\n", + " separator = '|---|'\n", + " v_starts = '| start |'\n", + " v_ends = '| end |'\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " header += f' vehicle {v} |'\n", + " separator += '---|'\n", + " v_starts += f' {starts[v]} |'\n", + " v_ends += f' {ends[v]} |'\n", + " print(header)\n", + " print(separator)\n", + " print(v_starts)\n", + " print(v_ends)\n", "\n", - "print('\\nNodes:')\n", - "print('| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices | routing.nodes | routing.Size |')\n", - "print('|---|---|---|---|---|')\n", - "print(f'| {locations} | {manager.GetNumberOfNodes()} | {manager.GetNumberOfIndices()} | {routing.nodes()} | {routing.Size()} |')\n", + " print('\\nNodes:')\n", + " print('| locations | manager.GetNumberOfNodes | manager.GetNumberOfIndices | routing.nodes | routing.Size |')\n", + " print('|---|---|---|---|---|')\n", + " print(f'| {locations} | {manager.GetNumberOfNodes()} | {manager.GetNumberOfIndices()} | {routing.nodes()} | {routing.Size()} |')\n", "\n", - "print('\\nLocations:')\n", - "print('| node | index | routing.IsStart | routing.IsEnd |')\n", - "print('|---|---|---|---|')\n", - "for node in range(manager.GetNumberOfNodes()):\n", - " if node in starts or node in ends:\n", - " continue\n", - " index = manager.NodeToIndex(node)\n", - " print(\n", - " f'| {node} | {index} | {routing.IsStart(index)} | {routing.IsEnd(index)} |'\n", - " )\n", + " print('\\nLocations:')\n", + " print('| node | index | routing.IsStart | routing.IsEnd |')\n", + " print('|---|---|---|---|')\n", + " for node in range(manager.GetNumberOfNodes()):\n", + " if node in starts or node in ends:\n", + " continue\n", + " index = manager.NodeToIndex(node)\n", + " print(\n", + " f'| {node} | {index} | {routing.IsStart(index)} | {routing.IsEnd(index)} |'\n", + " )\n", "\n", - "print('\\nStart/End:')\n", - "print('| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |')\n", - "print('|---|---|---|---|---|---|')\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " start_index = routing.Start(v)\n", - " start_node = manager.IndexToNode(start_index)\n", - " print(f'| {v} | start | {start_node} | {start_index} | {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |')\n", - "for v in range(manager.GetNumberOfVehicles()):\n", - " end_index = routing.End(v)\n", - " end_node = manager.IndexToNode(end_index)\n", - " print(f'| {v} | end | {end_node} | {end_index} | {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |')\n", + " print('\\nStart/End:')\n", + " print('| vehicle | Start/end | node | index | routing.IsStart | routing.IsEnd |')\n", + " print('|---|---|---|---|---|---|')\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " start_index = routing.Start(v)\n", + " start_node = manager.IndexToNode(start_index)\n", + " print(f'| {v} | start | {start_node} | {start_index} | {routing.IsStart(start_index)} | {routing.IsEnd(start_index)} |')\n", + " for v in range(manager.GetNumberOfVehicles()):\n", + " end_index = routing.End(v)\n", + " end_node = manager.IndexToNode(end_index)\n", + " print(f'| {v} | end | {end_node} | {end_index} | {routing.IsStart(end_index)} | {routing.IsEnd(end_index)} |')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb b/examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb index 6029a9fe38..b6e944fb5a 100644 --- a/examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb +++ b/examples/notebook/constraint_solver/vrp_pickup_delivery.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Pickup Delivery Problem (PDP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -170,7 +159,6 @@ " 536, 194, 798, 0\n", " ],\n", " ]\n", - " # [START pickups_deliveries]\n", " data['pickups_deliveries'] = [\n", " [1, 6],\n", " [2, 10],\n", @@ -181,14 +169,11 @@ " [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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -208,84 +193,69 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Define cost of each arc.\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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Define Transportation Requests.\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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_pickup_delivery_fifo.ipynb b/examples/notebook/constraint_solver/vrp_pickup_delivery_fifo.ipynb index 79691afb74..3808f10bb2 100644 --- a/examples/notebook/constraint_solver/vrp_pickup_delivery_fifo.ipynb +++ b/examples/notebook/constraint_solver/vrp_pickup_delivery_fifo.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Pickup Delivery Problem (PDP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -170,7 +159,6 @@ " 536, 194, 798, 0\n", " ],\n", " ]\n", - " # [START pickups_deliveries]\n", " data['pickups_deliveries'] = [\n", " [1, 6],\n", " [2, 10],\n", @@ -181,14 +169,11 @@ " [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", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -208,86 +193,71 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Define cost of each arc.\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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Define Transportation Requests.\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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(data, manager, routing, assignment)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_pickup_delivery_lifo.ipynb b/examples/notebook/constraint_solver/vrp_pickup_delivery_lifo.ipynb index 47121ef265..b8efb3ea97 100644 --- a/examples/notebook/constraint_solver/vrp_pickup_delivery_lifo.ipynb +++ b/examples/notebook/constraint_solver/vrp_pickup_delivery_lifo.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Pickup Delivery Problem (PDP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Pickup Delivery Problem (PDP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -170,7 +159,6 @@ " 536, 194, 798, 0\n", " ],\n", " ]\n", - " # [START pickups_deliveries]\n", " data['pickups_deliveries'] = [\n", " [1, 6],\n", " [2, 10],\n", @@ -181,14 +169,11 @@ " [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", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -208,86 +193,71 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Define cost of each arc.\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", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Define Transportation Requests.\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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PARALLEL_CHEAPEST_INSERTION)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(data, manager, routing, assignment)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_resources.ipynb b/examples/notebook/constraint_solver/vrp_resources.ipynb index 3bb851396d..a81b7cc946 100644 --- a/examples/notebook/constraint_solver/vrp_resources.ipynb +++ b/examples/notebook/constraint_solver/vrp_resources.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicles Routing Problem (VRP) with Resource Constraints.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP) with Resource Constraints.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -139,17 +128,13 @@ " (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, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -173,119 +158,98 @@ " print(plan_output)\n", " total_time += solution.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", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a 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", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Add resource constraints at the depot.\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", "\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", + " depot_usage = [1 for i in range(len(intervals))]\n", + " solver.Add(\n", + " solver.Cumulative(intervals, depot_usage, data['depot_capacity'],\n", + " 'depot'))\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", + " # Instantiate route start and end times to produce feasible 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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\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", - "else:\n", - " print('No solution found !')\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_starts_ends.ipynb b/examples/notebook/constraint_solver/vrp_starts_ends.ipynb index d7a16dec9d..1ca21670f2 100644 --- a/examples/notebook/constraint_solver/vrp_starts_ends.ipynb +++ b/examples/notebook/constraint_solver/vrp_starts_ends.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple Vehicles Routing Problem.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Simple Vehicles Routing Problem.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -171,15 +160,11 @@ " ],\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", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -199,75 +184,60 @@ " 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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),\n", + " data['num_vehicles'], data['starts'],\n", + " data['ends'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " # Convert from routing variable Index to distance matrix NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " to_node = manager.IndexToNode(to_index)\n", + " return data['distance_matrix'][from_node][to_node]\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_time_windows.ipynb b/examples/notebook/constraint_solver/vrp_time_windows.ipynb index 6630f3411b..555a5472d6 100644 --- a/examples/notebook/constraint_solver/vrp_time_windows.ipynb +++ b/examples/notebook/constraint_solver/vrp_time_windows.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicles Routing Problem (VRP) with Time Windows.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP) with Time Windows.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -141,10 +130,8 @@ " 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", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -168,95 +155,78 @@ " print(plan_output)\n", " total_time += solution.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", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a 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", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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 == data['depot']:\n", - " continue\n", - " index = manager.NodeToIndex(location_idx)\n", - " time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n", - "# Add time window constraints for each vehicle start node.\n", - "depot_idx = data['depot']\n", - "for vehicle_id in range(data['num_vehicles']):\n", - " index = routing.Start(vehicle_id)\n", - " time_dimension.CumulVar(index).SetRange(\n", - " data['time_windows'][depot_idx][0],\n", - " data['time_windows'][depot_idx][1])\n", - "# [END time_windows_constraint]\n", + " # Add 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 == data['depot']:\n", + " continue\n", + " index = manager.NodeToIndex(location_idx)\n", + " time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])\n", + " # Add time window constraints for each vehicle start node.\n", + " depot_idx = data['depot']\n", + " for vehicle_id in range(data['num_vehicles']):\n", + " index = routing.Start(vehicle_id)\n", + " time_dimension.CumulVar(index).SetRange(\n", + " data['time_windows'][depot_idx][0],\n", + " data['time_windows'][depot_idx][1])\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", + " # Instantiate route start and end times to produce feasible 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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\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", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_time_windows_per_vehicles.ipynb b/examples/notebook/constraint_solver/vrp_time_windows_per_vehicles.ipynb index 75ec678957..91172e27f3 100644 --- a/examples/notebook/constraint_solver/vrp_time_windows_per_vehicles.ipynb +++ b/examples/notebook/constraint_solver/vrp_time_windows_per_vehicles.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,27 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP) with Time Window (TW) per vehicle.\n", + "Vehicles Routing Problem (VRP) with Time Window (TW) per vehicle.\n", "\n", " All time are in minutes using 0am as origin\n", " e.g. 8am = 480, 11am = 660, 1pm = 780 ...\n", @@ -103,15 +87,20 @@ " location: [17-32] vehicle: 1 TW: [660, 780] (11am-1pm)\n", " location: [33-48] vehicle: 2 TW: [780, 900] (1pm-3pm)\n", " location: [49-64] vehicle: 3 TW: [900, 1020] (3pm-5pm)\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "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", @@ -137,10 +126,8 @@ " 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(manager, routing, assignment):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -189,138 +176,121 @@ " print(plan_output)\n", " total_time += duration\n", " print(f'Total duration of all routes: {total_time}min')\n", - " # [END solution_printer]\n", "\n", "\n", - "\"\"\"Solve the VRP with time windows.\"\"\"\n", - "# Instantiate the data problem.\n", - "# [START data]\n", - "data = create_data_model()\n", - "# [END data]\n", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\n", "\n", - "# Create the routing index manager.\n", - "# [START index_manager]\n", - "manager = pywrapcp.RoutingIndexManager(\n", - " 1 + 16*4, # number of locations\n", - " data['num_vehicles'],\n", - " data['depot'])\n", - "# [END index_manager]\n", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(\n", + " 1 + 16*4, # number of locations\n", + " data['num_vehicles'],\n", + " data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", - " # since our matrix is 17x17 map duplicated node to original one to\n", - " # retrieve the travel time\n", - " while from_node > 16:\n", - " from_node = from_node - 16;\n", - " while to_node > 16:\n", - " to_node = to_node - 16;\n", - " # add service of 25min for each location (except depot)\n", - " service_time = 0\n", - " if from_node != data['depot']:\n", - " service_time = 25\n", - " return data['time_matrix'][from_node][to_node] + service_time\n", + " # Create and register a 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", + " # since our matrix is 17x17 map duplicated node to original one to\n", + " # retrieve the travel time\n", + " while from_node > 16:\n", + " from_node = from_node - 16;\n", + " while to_node > 16:\n", + " to_node = to_node - 16;\n", + " # add service of 25min for each location (except depot)\n", + " service_time = 0\n", + " if from_node != data['depot']:\n", + " service_time = 25\n", + " return data['time_matrix'][from_node][to_node] + service_time\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", "\n", - "# Add Time Windows constraint.\n", - "# [START time_windows_constraint]\n", - "time = 'Time'\n", - "routing.AddDimension(\n", - " transit_callback_index,\n", - " 0, # allow waiting time (0 min)\n", - " 1020, # maximum time per vehicle (9 hours)\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 in range(17):\n", - " if location_idx == data['depot']:\n", - " continue\n", - " # Vehicle 0 location TW: [9am, 11am]\n", - " index_0 = manager.NodeToIndex(location_idx)\n", - " time_dimension.CumulVar(index_0).SetRange(540, 660)\n", - " routing.VehicleVar(index_0).SetValues([-1, 0])\n", + " # Add Time Windows constraint.\n", + " time = 'Time'\n", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 0, # allow waiting time (0 min)\n", + " 1020, # maximum time per vehicle (9 hours)\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 in range(17):\n", + " if location_idx == data['depot']:\n", + " continue\n", + " # Vehicle 0 location TW: [9am, 11am]\n", + " index_0 = manager.NodeToIndex(location_idx)\n", + " time_dimension.CumulVar(index_0).SetRange(540, 660)\n", + " routing.VehicleVar(index_0).SetValues([-1, 0])\n", "\n", - " # Vehicle 1 location TW: [11am, 1pm]\n", - " index_1 = manager.NodeToIndex(location_idx+16*1)\n", - " time_dimension.CumulVar(index_1).SetRange(660, 780)\n", - " routing.VehicleVar(index_1).SetValues([-1, 1])\n", + " # Vehicle 1 location TW: [11am, 1pm]\n", + " index_1 = manager.NodeToIndex(location_idx+16*1)\n", + " time_dimension.CumulVar(index_1).SetRange(660, 780)\n", + " routing.VehicleVar(index_1).SetValues([-1, 1])\n", "\n", - " # Vehicle 2 location TW: [1pm, 3pm]\n", - " index_2 = manager.NodeToIndex(location_idx+16*2)\n", - " time_dimension.CumulVar(index_2).SetRange(780, 900)\n", - " routing.VehicleVar(index_2).SetValues([-1, 2])\n", + " # Vehicle 2 location TW: [1pm, 3pm]\n", + " index_2 = manager.NodeToIndex(location_idx+16*2)\n", + " time_dimension.CumulVar(index_2).SetRange(780, 900)\n", + " routing.VehicleVar(index_2).SetValues([-1, 2])\n", "\n", - " # Vehicle 3 location TW: [3pm, 5pm]\n", - " index_3 = manager.NodeToIndex(location_idx+16*3)\n", - " time_dimension.CumulVar(index_3).SetRange(900, 1020)\n", - " routing.VehicleVar(index_3).SetValues([-1, 3])\n", + " # Vehicle 3 location TW: [3pm, 5pm]\n", + " index_3 = manager.NodeToIndex(location_idx+16*3)\n", + " time_dimension.CumulVar(index_3).SetRange(900, 1020)\n", + " routing.VehicleVar(index_3).SetValues([-1, 3])\n", "\n", - " # Add Disjunction so only one node among duplicate is visited\n", - " penalty = 100_000 # Give solver strong incentive to visit one node\n", - " routing.AddDisjunction([index_0, index_1, index_2, index_3], penalty, 1)\n", + " # Add Disjunction so only one node among duplicate is visited\n", + " penalty = 100_000 # Give solver strong incentive to visit one node\n", + " routing.AddDisjunction([index_0, index_1, index_2, index_3], penalty, 1)\n", "\n", - "# Add time window constraints for each vehicle start node.\n", - "depot_idx = data['depot']\n", - "for vehicle_id in range(data['num_vehicles']):\n", - " index = routing.Start(vehicle_id)\n", - " time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\n", + " # Add time window constraints for each vehicle start node.\n", + " depot_idx = data['depot']\n", + " for vehicle_id in range(data['num_vehicles']):\n", + " index = routing.Start(vehicle_id)\n", + " time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\n", "\n", - "# Add time window constraints for each vehicle end node.\n", - "depot_idx = data['depot']\n", - "for vehicle_id in range(data['num_vehicles']):\n", - " index = routing.End(vehicle_id)\n", - " time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\n", - "# [END time_windows_constraint]\n", + " # Add time window constraints for each vehicle end node.\n", + " depot_idx = data['depot']\n", + " for vehicle_id in range(data['num_vehicles']):\n", + " index = routing.End(vehicle_id)\n", + " time_dimension.CumulVar(index).SetRange(480, 1020) # (8am, 5pm)\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", + " # Instantiate route start and end times to produce feasible 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", "\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.time_limit.FromSeconds(1)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(1)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "assignment = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " assignment = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if assignment:\n", - " print_solution(manager, routing, assignment)\n", - "else:\n", - " print(\"no solution found !\")\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if assignment:\n", + " print_solution(manager, routing, assignment)\n", + " else:\n", + " print(\"no solution found !\")\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_tokens.ipynb b/examples/notebook/constraint_solver/vrp_tokens.ipynb index e99eab261f..0b37df8695 100644 --- a/examples/notebook/constraint_solver/vrp_tokens.ipynb +++ b/examples/notebook/constraint_solver/vrp_tokens.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Simple VRP with special locations which need to be visited at end of the route.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,25 +82,8 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Simple VRP with special locations which need to be visited at end of the route.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", "def create_data_model():\n", @@ -159,85 +150,85 @@ " print('Total token of all routes: {}'.format(total_token))\n", "\n", "\n", - "\"\"\"Solve the CVRP problem.\"\"\"\n", - "# Instantiate the data problem.\n", - "data = create_data_model()\n", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\n", "\n", - "# Create the routing index manager.\n", - "manager = pywrapcp.RoutingIndexManager(len(data['tokens']),\n", - " data['num_vehicles'], data['depot'])\n", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['tokens']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "# Create and register a transit callback.\n", - "def distance_callback(from_index, to_index):\n", - " \"\"\"Returns the distance between the two nodes.\"\"\"\n", - " del from_index\n", - " del to_index\n", - " return 10\n", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " del from_index\n", + " del to_index\n", + " return 10\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "routing.AddDimension(\n", - " transit_callback_index,\n", - " 0, # null slack\n", - " 3000, # maximum distance per vehicle\n", - " True, # start cumul to zero\n", - " 'distance')\n", - "distance_dimension = routing.GetDimensionOrDie('distance')\n", - "distance_dimension.SetGlobalSpanCostCoefficient(100)\n", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 0, # null slack\n", + " 3000, # maximum distance per vehicle\n", + " True, # start cumul to zero\n", + " 'distance')\n", + " distance_dimension = routing.GetDimensionOrDie('distance')\n", + " distance_dimension.SetGlobalSpanCostCoefficient(100)\n", "\n", - "# Define cost of each arc.\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", "\n", - "# Add Token constraint.\n", - "def token_callback(from_index):\n", - " \"\"\"Returns the number of token consumed by the node.\"\"\"\n", - " # Convert from routing variable Index to tokens NodeIndex.\n", - " from_node = manager.IndexToNode(from_index)\n", - " return data['tokens'][from_node]\n", + " # Add Token constraint.\n", + " def token_callback(from_index):\n", + " \"\"\"Returns the number of token consumed by the node.\"\"\"\n", + " # Convert from routing variable Index to tokens NodeIndex.\n", + " from_node = manager.IndexToNode(from_index)\n", + " return data['tokens'][from_node]\n", "\n", - "token_callback_index = routing.RegisterUnaryTransitCallback(token_callback)\n", - "routing.AddDimensionWithVehicleCapacity(\n", - " token_callback_index,\n", - " 0, # null capacity slack\n", - " data['vehicle_tokens'], # vehicle maximum tokens\n", - " False, # start cumul to zero\n", - " 'Token')\n", - "# Add constraint: special node can only be visited if token remaining is zero\n", - "token_dimension = routing.GetDimensionOrDie('Token')\n", - "for node in range(1, 6):\n", - " index = manager.NodeToIndex(node)\n", - " routing.solver().Add(token_dimension.CumulVar(index) == 0)\n", + " token_callback_index = routing.RegisterUnaryTransitCallback(token_callback)\n", + " routing.AddDimensionWithVehicleCapacity(\n", + " token_callback_index,\n", + " 0, # null capacity slack\n", + " data['vehicle_tokens'], # vehicle maximum tokens\n", + " False, # start cumul to zero\n", + " 'Token')\n", + " # Add constraint: special node can only be visited if token remaining is zero\n", + " token_dimension = routing.GetDimensionOrDie('Token')\n", + " for node in range(1, 6):\n", + " index = manager.NodeToIndex(node)\n", + " routing.solver().Add(token_dimension.CumulVar(index) == 0)\n", "\n", - "# Instantiate route start and end times to produce feasible times.\n", - "# [START depot_start_end_times]\n", - "for i in range(manager.GetNumberOfVehicles()):\n", - " routing.AddVariableMinimizedByFinalizer(\n", - " token_dimension.CumulVar(routing.Start(i)))\n", - " routing.AddVariableMinimizedByFinalizer(\n", - " token_dimension.CumulVar(routing.End(i)))\n", - "# [END depot_start_end_times]\n", + " # Instantiate route start and end times to produce feasible times.\n", + " for i in range(manager.GetNumberOfVehicles()):\n", + " routing.AddVariableMinimizedByFinalizer(\n", + " token_dimension.CumulVar(routing.Start(i)))\n", + " routing.AddVariableMinimizedByFinalizer(\n", + " token_dimension.CumulVar(routing.End(i)))\n", "\n", - "# Setting first solution heuristic.\n", - "search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "search_parameters.first_solution_strategy = (\n", - " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", - "search_parameters.local_search_metaheuristic = (\n", - " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", - "search_parameters.time_limit.FromSeconds(1)\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.time_limit.FromSeconds(1)\n", "\n", - "# Solve the problem.\n", - "solution = routing.SolveWithParameters(search_parameters)\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrp_with_time_limit.ipynb b/examples/notebook/constraint_solver/vrp_with_time_limit.ipynb index 2b593cc022..52103d61ff 100644 --- a/examples/notebook/constraint_solver/vrp_with_time_limit.ipynb +++ b/examples/notebook/constraint_solver/vrp_with_time_limit.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Vehicles Routing Problem (VRP).\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,29 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"Vehicles Routing Problem (VRP).\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(manager, routing, solution):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {solution.ObjectiveValue()}')\n", @@ -116,77 +105,62 @@ " 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", + "def main():\n", + " \"\"\"Solve the CVRP problem.\"\"\"\n", + " # Instantiate the data problem.\n", + " num_locations = 20\n", + " num_vehicles = 5\n", + " depot = 0\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(num_locations, num_vehicles, depot)\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", - " # pylint: disable=unused-argument\n", - " \"\"\"Returns the distance between the two nodes.\"\"\"\n", - " return 1\n", + " # Create and register a transit callback.\n", + " def distance_callback(from_index, to_index):\n", + " # pylint: disable=unused-argument\n", + " \"\"\"Returns the distance between the two nodes.\"\"\"\n", + " return 1\n", "\n", - "transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", - "# [END transit_callback]\n", + " transit_callback_index = routing.RegisterTransitCallback(distance_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\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", + " # Add 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", "\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(5)\n", - "# [END parameters]\n", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " search_parameters.local_search_metaheuristic = (\n", + " routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)\n", + " search_parameters.log_search = True\n", + " search_parameters.time_limit.FromSeconds(5)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(manager, routing, solution)\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(manager, routing, solution)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrpgs.ipynb b/examples/notebook/constraint_solver/vrpgs.ipynb index b7ba24c580..8279e9e152 100644 --- a/examples/notebook/constraint_solver/vrpgs.ipynb +++ b/examples/notebook/constraint_solver/vrpgs.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,28 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Copyright 2015 Tin Arm Engineering AB\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 (VRP).\n", + "Simple Vehicles Routing Problem (VRP).\n", "\n", " This is a sample using the routing library python wrapper to solve a VRP\n", " problem.\n", @@ -97,16 +80,21 @@ " http://en.wikipedia.org/wiki/Vehicle_routing_problem.\n", "\n", " Distances are in meters.\n", - "\"\"\"\n", - "\n", - "# [START import]\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import functools\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", @@ -140,10 +128,8 @@ " data['depot'] = 0\n", " return data\n", "\n", - "# [END data_model]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(data, manager, routing, assignment):\n", " \"\"\"Prints solution on console.\"\"\"\n", " print(f'Objective: {assignment.ObjectiveValue()}')\n", @@ -164,7 +150,6 @@ " total_distance += route_distance\n", " print('Total Distance of all routes: {}m'.format(total_distance))\n", "\n", - "# [END solution_printer]\n", "\n", "\n", "#######################\n", @@ -214,58 +199,44 @@ " distance_dimension.SetGlobalSpanCostCoefficient(100)\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", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\n", "\n", - "# Create the routing index manager.\n", - "# [START index_manager]\n", - "manager = pywrapcp.RoutingIndexManager(data['num_locations'],\n", - " data['num_vehicles'], data['depot'])\n", - "# [END index_manager]\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", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", - "# [END routing_model]\n", + " # Create Routing Model.\n", + " routing = pywrapcp.RoutingModel(manager)\n", "\n", - "# Define weight of each edge\n", - "# [START transit_callback]\n", - "distance_evaluator_index = routing.RegisterTransitCallback(\n", - " functools.partial(create_distance_evaluator(data), manager))\n", - "# [END transit_callback]\n", + " # Define weight of each edge\n", + " distance_evaluator_index = routing.RegisterTransitCallback(\n", + " functools.partial(create_distance_evaluator(data), manager))\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(distance_evaluator_index)\n", "\n", - "# Add Distance constraint.\n", - "# [START distance_constraint]\n", - "add_distance_dimension(routing, distance_evaluator_index)\n", - "# [END distance_constraint]\n", + " # Add Distance constraint.\n", + " add_distance_dimension(routing, distance_evaluator_index)\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution on console.\n", - "# [START print_solution]\n", - "if solution:\n", - " print_solution(data, manager, routing, solution)\n", - "else:\n", - " print('No solution found !')\n", - "# [END print_solution]\n", + " # Print solution on console.\n", + " if solution:\n", + " print_solution(data, manager, routing, solution)\n", + " else:\n", + " print('No solution found !')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/constraint_solver/vrptw_store_solution_data.ipynb b/examples/notebook/constraint_solver/vrptw_store_solution_data.ipynb index 752c088e03..7a54eaa191 100644 --- a/examples/notebook/constraint_solver/vrptw_store_solution_data.ipynb +++ b/examples/notebook/constraint_solver/vrptw_store_solution_data.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "VRPTW example that stores routes and cumulative data in an array.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,30 +82,10 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "# [START program]\n", - "\"\"\"VRPTW example that stores routes and cumulative data in an array.\"\"\"\n", - "\n", - "# [START import]\n", "from ortools.constraint_solver import routing_enums_pb2\n", "from ortools.constraint_solver import pywrapcp\n", - "# [END import]\n", "\n", "\n", - "# [START program_part1]\n", - "# [START data_model]\n", "def create_data_model():\n", " \"\"\"Stores the data for the problem.\"\"\"\n", " data = {}\n", @@ -143,10 +131,8 @@ " data['depot'] = 0\n", " return data\n", "\n", - "# [END data_model]\n", "\n", "\n", - "# [START solution_printer]\n", "def print_solution(routes, cumul_data):\n", " \"\"\"Print the solution.\"\"\"\n", " total_time = 0\n", @@ -167,10 +153,8 @@ " route_str += 'Total time: {} min'.format(total_time)\n", " print(route_str)\n", "\n", - "# [END solution_printer]\n", "\n", "\n", - "# [START get_routes]\n", "def get_routes(solution, routing, manager):\n", " \"\"\"Get vehicle routes from a solution and store them in an array.\"\"\"\n", " # Get vehicle routes and store them in a two dimensional array whose\n", @@ -185,10 +169,8 @@ " routes.append(route)\n", " return routes\n", "\n", - "# [END get_routes]\n", "\n", "\n", - "# [START get_cumulative_data]\n", "def get_cumul_data(solution, routing, dimension):\n", " \"\"\"Get cumulative data from a dimension and store it in an array.\"\"\"\n", " # Returns an array cumul_data whose i,j entry contains the minimum and\n", @@ -209,96 +191,79 @@ " cumul_data.append(route_data)\n", " return cumul_data\n", "\n", - "# [END get_cumulative_data]\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", + "def main():\n", + " \"\"\"Solve the VRP with time windows.\"\"\"\n", + " # Instantiate the data problem.\n", + " data = create_data_model()\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", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),\n", + " data['num_vehicles'], data['depot'])\n", "\n", - "# Create Routing Model.\n", - "# [START routing_model]\n", - "routing = pywrapcp.RoutingModel(manager)\n", + " # Create 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", + " # Create and register a 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", + " transit_callback_index = routing.RegisterTransitCallback(time_callback)\n", "\n", - "# Define cost of each arc.\n", - "# [START arc_cost]\n", - "routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", - "# [END arc_cost]\n", + " # Define cost of each arc.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)\n", "\n", - "# Add Time Windows constraint.\n", - "# [START time_windows_constraint]\n", - "time = 'Time'\n", + " # Add Time Windows constraint.\n", + " time = 'Time'\n", "\n", - "routing.AddDimension(\n", - " transit_callback_index,\n", - " 30, # allow waiting time\n", - " 30, # maximum time per vehicle\n", - " False, # Don't force cumulative time to be 0 at start of routes.\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", + " routing.AddDimension(\n", + " transit_callback_index,\n", + " 30, # allow waiting time\n", + " 30, # maximum time per vehicle\n", + " False, # Don't force cumulative time to be 0 at start of routes.\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", "\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", + " # Instantiate route start and end times to produce feasible 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", "\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", + " # Setting first solution heuristic.\n", + " search_parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " search_parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", "\n", - "# Solve the problem.\n", - "# [START solve]\n", - "solution = routing.SolveWithParameters(search_parameters)\n", - "# [END solve]\n", + " # Solve the problem.\n", + " solution = routing.SolveWithParameters(search_parameters)\n", "\n", - "# Print solution.\n", - "# [START print_solution]\n", - "if solution:\n", - " routes = get_routes(solution, routing, manager)\n", - " cumul_data = get_cumul_data(solution, routing, time_dimension)\n", - " print_solution(routes, cumul_data)\n", - "# [END print_solution]\n", + " # Print solution.\n", + " if solution:\n", + " routes = get_routes(solution, routing, manager)\n", + " cumul_data = get_cumul_data(solution, routing, time_dimension)\n", + " print_solution(routes, cumul_data)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/3_jugs_mip.ipynb b/examples/notebook/contrib/3_jugs_mip.ipynb index 2931c49a9f..0d84b2c363 100644 --- a/examples/notebook/contrib/3_jugs_mip.ipynb +++ b/examples/notebook/contrib/3_jugs_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " 3 jugs problem using MIP in Google or-tools.\n", "\n", @@ -101,138 +86,158 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " # using GLPK\n", + " if sol == 'GLPK':\n", + " solver = pywraplp.Solver('CoinsGridGLPK',\n", + " pywraplp.Solver.GLPK_MIXED_INTEGER_PROGRAMMING)\n", " else:\n", - " solver.Add(rhs[i] == 0)\n", + " # Using CBC\n", + " solver = pywraplp.Solver('CoinsGridCBC',\n", + " pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\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", + " # data\n", + " #\n", + " n = 15\n", + " start = 0 # start node\n", + " end = 14 # end node\n", + " M = 999 # a large number\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", + " 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", - "# inflow = outflow\n", - "for i in range(n):\n", - " solver.Add(out_flow[i] - in_flow[i] == rhs[i])\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", - "# objective\n", - "objective = solver.Minimize(z)\n", + " #\n", + " # variables\n", + " #\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " # requirements (right hand statement)\n", + " rhs = [solver.IntVar(-1, 1, 'rhs[%i]' % i) for i in range(n)]\n", "\n", - "print()\n", - "print('z: ', int(solver.Objective().Value()))\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", - "t = start\n", - "while t != end:\n", - " print(nodes[t], '->', end=' ')\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", - " if x[t, j].SolutionValue() == 1:\n", - " print(nodes[j])\n", - " t = j\n", - " break\n", + " solver.Add(\n", + " in_flow[j] == solver.Sum([x[i, j] for i in range(n) if d[i][j] < M]))\n", "\n", - "print()\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "if sol == 'CBC':\n", - " print('iterations:', solver.Iterations())\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", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/3_jugs_regular.ipynb b/examples/notebook/contrib/3_jugs_regular.ipynb index 74addaf5ce..f7f829e96c 100644 --- a/examples/notebook/contrib/3_jugs_regular.ipynb +++ b/examples/notebook/contrib/3_jugs_regular.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " 3 jugs problem using regular constraint in Google CP Solver.\n", "\n", @@ -121,8 +106,16 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "from collections import defaultdict\n", "\n", @@ -196,137 +189,147 @@ " a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n", "\n", "\n", + "def main(n):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('3 jugs problem using regular constraint')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('3 jugs problem using regular constraint')\n", "\n", - "#\n", - "# data\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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " # solution and search\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\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", + " 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", + " 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", + " 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", + " # 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." + "# the length of the state array.\n", + "for n in range(1, 15):\n", + " result = main(n)\n", + " result_len = len(result)\n", + " if result_len:\n", + " print()\n", + " print('Found a solution of length %i:' % result_len, result)\n", + " print()\n", + " break\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/a_round_of_golf.ipynb b/examples/notebook/contrib/a_round_of_golf.ipynb index 8720434ac4..2ff0afcd88 100644 --- a/examples/notebook/contrib/a_round_of_golf.ipynb +++ b/examples/notebook/contrib/a_round_of_golf.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " A Round of Golf puzzle (Dell Logic Puzzles) in Google CP Solver.\n", "\n", @@ -138,103 +123,115 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"All interval\")\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", + " # 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", + " # 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", + " 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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/all_interval.ipynb b/examples/notebook/contrib/all_interval.ipynb index b2485cee8c..ec286d5b93 100644 --- a/examples/notebook/contrib/all_interval.ipynb +++ b/examples/notebook/contrib/all_interval.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " All interval problem in Google CP Solver.\n", "\n", @@ -124,65 +109,79 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(n=12):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"All interval\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"All interval\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"n:\", 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " 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", + " 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", + " 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" + "\n", + "n = 12\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/alldifferent_except_0.ipynb b/examples/notebook/contrib/alldifferent_except_0.ipynb index 9a2826093d..c8fa4af119 100644 --- a/examples/notebook/contrib/alldifferent_except_0.ipynb +++ b/examples/notebook/contrib/alldifferent_except_0.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " All different except 0 Google CP Solver.\n", "\n", @@ -122,9 +107,17 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "#\n", @@ -153,47 +146,51 @@ " ]\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Alldifferent except 0\")\n", + "def main(unused_argv):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Alldifferent except 0\")\n", "\n", - "# data\n", - "n = 7\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", + " # 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", + " # constraints\n", + " #\n", + " alldifferent_except_0(solver, x)\n", "\n", - "# we require 2 0's\n", - "solver.Add(z == 2)\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", + " # 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", + " 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", + " 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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/alphametic.ipynb b/examples/notebook/contrib/alphametic.ipynb index c2f47acbe2..d852b8bd87 100644 --- a/examples/notebook/contrib/alphametic.ipynb +++ b/examples/notebook/contrib/alphametic.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Generic alphametic solver in Google CP Solver.\n", "\n", @@ -117,99 +102,109 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "import re\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(problem_str=\"SEND+MORE=MONEY\", base=10):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Send most money\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Send most money\")\n", "\n", - "# data\n", - "print(\"\\nproblem:\", problem_str)\n", + " # data\n", + " print(\"\\nproblem:\", problem_str)\n", "\n", - "# convert to array.\n", - "problem = re.split(\"[\\s+=]\", problem_str)\n", + " # convert to array.\n", + " problem = re.split(\"[\\s+=]\", problem_str)\n", "\n", - "p_len = len(problem)\n", - "print(\"base:\", base)\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", + " # 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", + " # length of each number\n", + " lens = list(map(len, problem))\n", "\n", - "#\n", - "# declare variables\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", + " # 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", + " # 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", + " ix = 0\n", " for prob in problem:\n", - " for p in prob:\n", - " print(p, end=\" \")\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", - " print()\n", - " for prob in problem:\n", - " for p in prob:\n", - " print(x[lookup[p]].Value(), end=\" \")\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(\"sums:\", [sums[i].Value() for i in range(p_len)])\n", - " print()\n", + " print(\"\\nnum_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", @@ -223,7 +218,17 @@ "\n", "\n", "problem = \"SEND+MORE=MONEY\"\n", - "base = 10\n" + "base = 10\n", + "if len(sys.argv) > 1:\n", + " problem = sys.argv[1]\n", + "if len(sys.argv) > 2:\n", + " base = int(sys.argv[2])\n", + "\n", + "if problem == \"TEST\" or problem == \"test\":\n", + " test_problems(base)\n", + "else:\n", + " main(problem, base)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/assignment.ipynb b/examples/notebook/contrib/assignment.ipynb index bb13613a90..4c55219fd6 100644 --- a/examples/notebook/contrib/assignment.ipynb +++ b/examples/notebook/contrib/assignment.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Assignment problem in Google CP Solver.\n", "\n", @@ -104,94 +89,106 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(cost, rows, cols):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"n-queens\")\n", "\n", - "#\n", - "# data\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", + " # 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", - " print(x[i][j].Value(), end=\" \")\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", - "\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", + " 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", + "# interesting\n", + "rows = 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", + "main(cost, rows, cols)\n", "\n" ] } diff --git a/examples/notebook/contrib/assignment6_mip.ipynb b/examples/notebook/contrib/assignment6_mip.ipynb index 26fba5741c..c405a2c19e 100644 --- a/examples/notebook/contrib/assignment6_mip.ipynb +++ b/examples/notebook/contrib/assignment6_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Assignment problem using MIP in Google or-tools.\n", "\n", @@ -113,112 +98,132 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", - "print('Solver: ', sol)\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", + " # 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", + " # data\n", + " #\n", "\n", - "# number of agents\n", - "m = 8\n", + " # number of agents\n", + " m = 8\n", "\n", - "# number of tasks\n", - "n = 8\n", + " # number of tasks\n", + " n = 8\n", "\n", - "# set of agents\n", - "I = list(range(m))\n", + " # set of agents\n", + " I = list(range(m))\n", "\n", - "# set of tasks\n", - "J = list(range(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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " # 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", + " # 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", + " # each task must be assigned exactly to one agent\n", " for j in J:\n", - " print(int(x[i, j].SolutionValue()), end=' ')\n", - " print()\n", - "print()\n", + " solver.Add(solver.Sum([x[i, j] for i in I]) == 1)\n", "\n", - "print()\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "if sol == 'CBC':\n", - " print('iterations:', solver.Iterations())\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", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/bacp.ipynb b/examples/notebook/contrib/bacp.ipynb index 440013c7d2..cb658bd77c 100644 --- a/examples/notebook/contrib/bacp.ipynb +++ b/examples/notebook/contrib/bacp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -124,41 +124,45 @@ " return (credits, nb_periods, prereq)\n", "\n", "\n", - "#------------------solver and variable declaration-------------\n", + "def main(args):\n", + " #------------------solver and variable declaration-------------\n", "\n", - "credits, nb_periods, prereq = ReadData(args.data)\n", - "nb_courses = len(credits)\n", + " credits, nb_periods, prereq = ReadData(args.data)\n", + " nb_courses = len(credits)\n", "\n", - "solver = pywrapcp.Solver('Balanced Academic Curriculum Problem')\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", + " 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", + " #-------------------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", + " # 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", + " #----------------Objective-------------------------------\n", "\n", - "objective_var = solver.Max(load_vars)\n", - "objective = solver.Minimize(objective_var, 1)\n", + " objective_var = solver.Max(load_vars)\n", + " objective = solver.Minimize(objective_var, 1)\n", "\n", - "#------------start the search and optimization-----------\n", + " #------------start the search and optimization-----------\n", "\n", - "db = solver.Phase(x, solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n", - " solver.INT_VALUE_DEFAULT)\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", + " search_log = solver.SearchLog(100000, objective_var)\n", + " solver.Solve(db, [objective, search_log])\n", + "\n", + "\n", + "main(parser.parse_args())\n", "\n" ] } diff --git a/examples/notebook/contrib/blending.ipynb b/examples/notebook/contrib/blending.ipynb index 665a41aa4b..7104a78bbb 100644 --- a/examples/notebook/contrib/blending.ipynb +++ b/examples/notebook/contrib/blending.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Blending problem in Google or-tools.\n", "\n", @@ -95,120 +80,140 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " # 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", + " # 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", + " 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", + " # 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", + " z = solver.NumVar(0, solver.Infinity(), 'z')\n", "\n", - "#\n", - "# constraints\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", + " 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", + " 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", + " solver.Add(solver.Sum(metal) == Alloy)\n", "\n", - "objective = solver.Minimize(z)\n", + " objective = solver.Minimize(z)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\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", + " 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", + " 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", + " 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", + " 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", + " print('Metals')\n", + " for i in Metals:\n", + " print(metal[i].SolutionValue(), end=' ')\n", + " print()\n", "\n", - "print()\n", + " print()\n", "\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "if sol == 'CBC':\n", - " print('iterations:', solver.Iterations())\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " if sol == 'CBC':\n", + " print('iterations:', solver.Iterations())\n", + "\n", + "\n", + "sol = 'CBC'\n", + "\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/broken_weights.ipynb b/examples/notebook/contrib/broken_weights.ipynb index 0605d0ca49..358006b701 100644 --- a/examples/notebook/contrib/broken_weights.ipynb +++ b/examples/notebook/contrib/broken_weights.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Broken weights problem in Google CP Solver.\n", "\n", @@ -120,91 +105,107 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(m=40, n=4):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Broken weights')\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", + " #\n", + " # data\n", + " #\n", + " print('total weight (m):', m)\n", + " print('number of pieces (n):', n)\n", " print()\n", - " print('-' * 30)\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", - " print('weight %2i:' % (i + 1), end=' ')\n", " for j in range(n):\n", - " print('%3i ' % x[i, j].Value(), end=' ')\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", - "print()\n", - "solver.EndSearch()\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", - "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" + "n = 4\n", + "if len(sys.argv) > 1:\n", + " m = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " n = int(sys.argv[2])\n", + "main(m, n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/bus_schedule.ipynb b/examples/notebook/contrib/bus_schedule.ipynb index 88fae9fce9..22920717e4 100644 --- a/examples/notebook/contrib/bus_schedule.ipynb +++ b/examples/notebook/contrib/bus_schedule.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Bus scheduling in Google CP Solver.\n", "\n", @@ -107,74 +92,90 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(num_buses_check=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Bus scheduling\")\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " 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", + " # 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", + " 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", + " 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", + " 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", + "\n", + "print(\"Check for minimun number of buses\")\n", + "num_buses_check = main()\n", + "print(\"... got \", num_buses_check, \"buses\")\n", + "print(\"All solutions:\")\n", + "main(num_buses_check)\n", "\n" ] } diff --git a/examples/notebook/contrib/car.ipynb b/examples/notebook/contrib/car.ipynb index d2af5a9375..725a75eafe 100644 --- a/examples/notebook/contrib/car.ipynb +++ b/examples/notebook/contrib/car.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Car sequencing in Google CP Solver.\n", "\n", @@ -102,111 +87,125 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(num_sol=3):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Car sequence\")\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", + " # 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", + " 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", + " # 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", + " 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", + " 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", + " 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", + " # 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", + " # 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 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", + " 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", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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" + "num_sol = 3\n", + "if len(sys.argv) > 1:\n", + " num_sol = int(sys.argv[1])\n", + "main(num_sol)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/check_dependencies.ipynb b/examples/notebook/contrib/check_dependencies.ipynb index 8be581fa79..a63a304dc8 100644 --- a/examples/notebook/contrib/check_dependencies.ipynb +++ b/examples/notebook/contrib/check_dependencies.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -116,6 +116,77 @@ " directory = dirname(directory)\n", " return directory\n", "\n", + "\n", + "parser = OptionParser(\"Log level\")\n", + "parser.add_option(\n", + " \"-l\",\n", + " \"--log\",\n", + " type=\"string\",\n", + " help=\n", + " \"Available levels are CRITICAL (3), ERROR (2), WARNING (1), INFO (0), DEBUG (-1)\",\n", + " default=\"INFO\")\n", + "options, args = parser.parse_args()\n", + "\n", + "try:\n", + " loglevel = getattr(logging, options.log.upper())\n", + "except AttributeError:\n", + " loglevel = {\n", + " 3: logging.CRITICAL,\n", + " 2: logging.ERROR,\n", + " 1: logging.WARNING,\n", + " 0: logging.INFO,\n", + " -1: logging.DEBUG,\n", + " }[int(options.log)]\n", + "\n", + "logging.basicConfig(\n", + " format=\"[%(levelname)s] %(message)s\", stream=sys.stdout, level=loglevel)\n", + "\n", + "logging.info(\"Python path : \" + sys.executable)\n", + "logging.info(\"Python version : \" + sys.version)\n", + "logging.info(\"sys.path : \" + str(sys.path))\n", + "ortools_project_path = n_dirname(\n", + " 3, abspath(inspect.getfile(inspect.currentframe())))\n", + "\n", + "#try to import ortools\n", + "try:\n", + " import ortools\n", + "except ImportError:\n", + " logging.error(notinstalled(\"ortools\"))\n", + " raise SystemExit\n", + "\n", + "#check if we're using ortools from the sources or it's binded by pypi's module\n", + "ortools_module_file = inspect.getfile(ortools)\n", + "ortools_module_path = n_dirname(3, ortools_module_file)\n", + "if (ortools_module_path == ortools_project_path):\n", + " logging.info(\"Or-tools is imported from : \" + ortools_module_file)\n", + "else:\n", + " log_error_and_exit(wrong_module(ortools_module_file, \"ortools\"))\n", + "\n", + "# Check if python can load the libraries' modules\n", + "# this is useful when the library architecture is not compatbile with the python executable,\n", + "# or when the library's dependencies are not available or not compatible.\n", + "from ortools.constraint_solver import _pywrapcp\n", + "from ortools.linear_solver import _pywraplp\n", + "from ortools.algorithms import _pywrapknapsack_solver\n", + "from ortools.graph import _pywrapgraph\n", + "\n", + "#try to import protobuf\n", + "try:\n", + " import google.protobuf\n", + "except ImportError:\n", + " log_error_and_exit(notinstalled(\"protobuf\"))\n", + "\n", + "#check if we're using protobuf from the sources or it's binded by pypi's module\n", + "protobuf_module_file = inspect.getfile(google.protobuf)\n", + "protobuf_module_path = n_dirname(7, protobuf_module_file)\n", + "if (protobuf_module_path == ortools_project_path):\n", + " logging.info(\"Protobuf is imported from : \" + protobuf_module_file)\n", + "else:\n", + " log_error_and_exit(wrong_module(protobuf_module_file, \"protobuf\"))\n", + "\n", + "#Check if the protobuf modules were successfully generated\n", + "from google.protobuf import descriptor as _descriptor\n", + "from google.protobuf import descriptor_pb2\n", "\n" ] } diff --git a/examples/notebook/contrib/circuit.ipynb b/examples/notebook/contrib/circuit.ipynb index 4cc1baf592..287073905c 100644 --- a/examples/notebook/contrib/circuit.ipynb +++ b/examples/notebook/contrib/circuit.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Decomposition of the circuit constraint in Google CP Solver.\n", "\n", @@ -115,9 +100,17 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -158,46 +151,53 @@ " solver.Add(z[n - 1] == 0)\n", "\n", "\n", + "def main(n=5):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Send most money\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Send most money\")\n", "\n", - "# data\n", - "print(\"n:\", 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", + " # 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", + " # constraints\n", + " #\n", + " circuit(solver, x)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", "\n", - "collector = solver.AllSolutionCollector(solution)\n", + " collector = solver.AllSolutionCollector(solution)\n", "\n", - "solver.Solve(\n", - " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n", - " [collector])\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", + " 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", + " 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" + "\n", + "n = 5\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/coins3.ipynb b/examples/notebook/contrib/coins3.ipynb index 42d41911ab..69e25b0792 100644 --- a/examples/notebook/contrib/coins3.ipynb +++ b/examples/notebook/contrib/coins3.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Coin application in Google CP Solver.\n", "\n", @@ -111,67 +96,79 @@ " 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", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Coins\")\n", + "def main():\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", + " # 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", + " # 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", + " # constraints\n", + " #\n", "\n", - "# number of used coins, to be minimized\n", - "solver.Add(num_coins == solver.Sum(x))\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", + " # 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", + " # 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", + " # 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", + " 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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/coins_grid.ipynb b/examples/notebook/contrib/coins_grid.ipynb index 598c637c8b..8259840a24 100644 --- a/examples/notebook/contrib/coins_grid.ipynb +++ b/examples/notebook/contrib/coins_grid.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Coins grid problem in Google CP Solver.\n", "\n", " Problem from\n", @@ -125,67 +110,87 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Coins grid\")\n", - "# data\n", + "def main(n, c):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Coins grid\")\n", + " # data\n", "\n", - "print(\"n: \", n)\n", - "print(\"c: \", c)\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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(\"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", - "print()\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "# data\n", + "n = 5 # the grid size\n", + "c = 2 # number of coins per row/column\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " c = int(sys.argv[2])\n", + "\n", + "main(n, c)\n", "\n" ] } diff --git a/examples/notebook/contrib/coins_grid_mip.ipynb b/examples/notebook/contrib/coins_grid_mip.ipynb index f30c3f427a..3777fc78ef 100644 --- a/examples/notebook/contrib/coins_grid_mip.ipynb +++ b/examples/notebook/contrib/coins_grid_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Coins grid problem in Google CP Solver.\n", "\n", @@ -114,62 +99,74 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.linear_solver import pywraplp\n", "\n", "\n", - "# Create the solver.\n", + "def main(unused_argv):\n", + " # Create the solver.\n", "\n", - "# using CBC\n", - "solver = pywraplp.Solver('CoinsGridCBC',\n", - " pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # objective\n", + " objective = solver.Minimize(objective_var)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\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", + " 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", - "print()\n", "\n", - "print()\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "# print 'iterations:', solver.Iterations()\n", + " print()\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " # print 'iterations:', solver.Iterations()\n", + "\n", + "\n", + "main('coin grids')\n", "\n" ] } diff --git a/examples/notebook/contrib/coloring_ip.ipynb b/examples/notebook/contrib/coloring_ip.ipynb index b1edc06228..27db650479 100644 --- a/examples/notebook/contrib/coloring_ip.ipynb +++ b/examples/notebook/contrib/coloring_ip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Simple coloring problem using MIP in Google CP Solver.\n", "\n", @@ -110,105 +95,125 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " 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", + " # data\n", + " #\n", "\n", - "# max number of colors\n", - "# [we know that 4 suffices for normal maps]\n", - "nc = 5\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", + " # number of nodes\n", + " n = 11\n", + " # set of nodes\n", + " V = list(range(n))\n", "\n", - "num_edges = 20\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # number of colors used, to minimize\n", + " obj = solver.Sum(u)\n", "\n", - "#\n", - "# constraints\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", + " # 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", + " # 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", + " # objective\n", + " objective = solver.Minimize(obj)\n", "\n", - "#\n", - "# solution\n", - "#\n", - "solver.Solve()\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", + " 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", + " 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", + " print()\n", + " print('WallTime:', solver.WallTime())\n", + " if sol == 'CBC':\n", + " print('iterations:', solver.Iterations())\n", + "\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/combinatorial_auction2.ipynb b/examples/notebook/contrib/combinatorial_auction2.ipynb index 99dd17c949..621bbb2cd6 100644 --- a/examples/notebook/contrib/combinatorial_auction2.ipynb +++ b/examples/notebook/contrib/combinatorial_auction2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", + "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", @@ -102,80 +87,92 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from collections import *\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Problem\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Problem\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "N = 5\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", + " # 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", + " # [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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/contiguity_regular.ipynb b/examples/notebook/contrib/contiguity_regular.ipynb index e8eea4e2c8..66408f2480 100644 --- a/examples/notebook/contrib/contiguity_regular.ipynb +++ b/examples/notebook/contrib/contiguity_regular.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Global constraint contiguity using regularin Google CP Solver.\n", "\n", @@ -113,8 +98,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "#\n", @@ -187,63 +180,67 @@ " a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Global contiguity using regular')\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", + " # 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", + " # 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", + " # 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 = 7\n", "\n", - "#\n", - "# declare variables\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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " 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", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/costas_array.ipynb b/examples/notebook/contrib/costas_array.ipynb index 9af88293ea..2046b42f1b 100644 --- a/examples/notebook/contrib/costas_array.ipynb +++ b/examples/notebook/contrib/costas_array.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Costas array in Google CP Solver.\n", "\n", @@ -133,109 +118,123 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(n=6):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Costas array\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Costas array\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"n:\", 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", + " #\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", - " v = differences[i, j].Value()\n", - " if v == -n + 1:\n", - " print(\" \", end=\" \")\n", - " else:\n", - " print(\"%2d\" % v, end=\" \")\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", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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" + "n = 6\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/covering_opl.ipynb b/examples/notebook/contrib/covering_opl.ipynb index 2602fb3114..ae9e626a46 100644 --- a/examples/notebook/contrib/covering_opl.ipynb +++ b/examples/notebook/contrib/covering_opl.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering problem in Google CP Solver.\n", "\n", @@ -129,87 +114,99 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set covering\")\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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " 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", + " # 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", + " # search and result\n", + " #\n", + " db = solver.Phase(Hire, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n", "\n", - "solver.NewSearch(db, [objective])\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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/crew.ipynb b/examples/notebook/contrib/crew.ipynb index 975c18be4d..bdc2a11006 100644 --- a/examples/notebook/contrib/crew.ipynb +++ b/examples/notebook/contrib/crew.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Crew allocation problem in Google CP Solver.\n", "\n", @@ -111,172 +96,187 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(sols=1):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Crew\")\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", + " # 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", + " 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", + " 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", + " # 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", + " 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", + " #\n", + " # declare variables\n", + " #\n", + " crew = {}\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", + " 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", - " 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", + " # number of working persons\n", + " num_working = solver.IntVar(1, num_persons, \"num_working\")\n", "\n", - " print(\"Crew:\")\n", - " for person in range(num_persons):\n", - " print(\"%-10s flights\" % names[person], end=\" \")\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", - " if crew[flight, person].Value() == 1:\n", - " print(flight, end=\" \")\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", - " 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", + "num_solutions_to_show = 1\n", + "if (len(sys.argv) > 1):\n", + " num_solutions_to_show = int(sys.argv[1])\n", "\n", - "num_solutions_to_show = 1\n" + "main(num_solutions_to_show)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/crossword2.ipynb b/examples/notebook/contrib/crossword2.ipynb index d2162e66dc..6928087458 100644 --- a/examples/notebook/contrib/crossword2.ipynb +++ b/examples/notebook/contrib/crossword2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Crosswords in Google CP Solver.\n", "\n", @@ -130,133 +115,143 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Problem\")\n", + "def main():\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", + " # 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", + " 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", + " 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 = 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", + " # 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", + " 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", + " # 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", + " 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", + " 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", + " # 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", + " # 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", + " # 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", + " 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", - "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", @@ -264,6 +259,8 @@ " print(\"\".join(\n", " [\"%s\" % (alpha[A[ee, ii].Value()]) for ii in range(word_len)]))\n", "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/crypta.ipynb b/examples/notebook/contrib/crypta.ipynb index b35f9f7d3e..fe1823e09d 100644 --- a/examples/notebook/contrib/crypta.ipynb +++ b/examples/notebook/contrib/crypta.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Cryptarithmetic puzzle in Google CP Solver.\n", "\n", @@ -117,72 +102,84 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Crypta\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Crypta\")\n", "\n", - "#\n", - "# data\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", + " # 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", + " 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", + " # 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", + " 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", + " 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", + " 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", + " # search and result\n", + " #\n", + " db = solver.Phase(LD, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n", "\n", - "solver.NewSearch(db)\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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/crypto.ipynb b/examples/notebook/contrib/crypto.ipynb index e879009850..2366781436 100644 --- a/examples/notebook/contrib/crypto.ipynb +++ b/examples/notebook/contrib/crypto.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Crypto problem in Google CP Solver.\n", "\n", @@ -116,95 +101,107 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Crypto problem\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Crypto problem\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_letters = 26\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", + " 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", + " # 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", + " # 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", + " # 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", + " 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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/curious_set_of_integers.ipynb b/examples/notebook/contrib/curious_set_of_integers.ipynb index d2c32b4bb3..7229c48603 100644 --- a/examples/notebook/contrib/curious_set_of_integers.ipynb +++ b/examples/notebook/contrib/curious_set_of_integers.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Crypto problem in Google CP Solver.\n", "\n", @@ -132,8 +117,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", @@ -142,59 +135,63 @@ " solver.Add(x[i] <= x[i + 1])\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Curious set of integers\")\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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " 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", + " 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", + " 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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/debruijn_binary.ipynb b/examples/notebook/contrib/debruijn_binary.ipynb index 8695f7bb56..06aa1118bb 100644 --- a/examples/notebook/contrib/debruijn_binary.ipynb +++ b/examples/notebook/contrib/debruijn_binary.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " de Bruijn sequences in Google CP Solver.\n", "\n", @@ -115,8 +100,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -129,134 +122,145 @@ " 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", + "def main(base=2, n=3, m=8):\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", + " # 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", + " # base = 4\n", + " # n = 4\n", + " # m = base**n\n", "\n", - "# harder problem\n", - "#base = 13\n", - "#n = 4\n", - "#m = 52\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", + " # 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", + " # 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", + " 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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " # ... 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " 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", - "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" + "m = base**n\n", + "if len(sys.argv) > 1:\n", + " base = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " n = int(sys.argv[2])\n", + "if len(sys.argv) > 3:\n", + " m = int(sys.argv[3])\n", + "\n", + "main(base, n, m)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/diet1.ipynb b/examples/notebook/contrib/diet1.ipynb index 7a4750b943..3a8ab98cda 100644 --- a/examples/notebook/contrib/diet1.ipynb +++ b/examples/notebook/contrib/diet1.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Simple diet problem in Google CP Solver.\n", "\n", @@ -117,58 +102,70 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.sat.python import cp_model\n", "\n", "\n", - "# Create the solver.\n", - "model = cp_model.CpModel()\n", + "def main(unused_argv):\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # objective\n", + " model.Minimize(cost)\n", "\n", - "# Solve model.\n", - "solver = cp_model.CpSolver()\n", - "status = solver.Solve(model)\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", + " # 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", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/diet1_b.ipynb b/examples/notebook/contrib/diet1_b.ipynb index 426841ad6d..69429b2808 100644 --- a/examples/notebook/contrib/diet1_b.ipynb +++ b/examples/notebook/contrib/diet1_b.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Simple diet problem in Google CP Solver.\n", "\n", @@ -119,66 +104,78 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Diet\")\n", + "def main(unused_argv):\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/diet1_mip.ipynb b/examples/notebook/contrib/diet1_mip.ipynb index 1a51693031..36a4690fed 100644 --- a/examples/notebook/contrib/diet1_mip.ipynb +++ b/examples/notebook/contrib/diet1_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Simple diet problem using MIP in Google CP Solver.\n", "\n", @@ -108,68 +93,88 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # objective\n", + " objective = solver.Minimize(cost)\n", "\n", - "#\n", - "# solution\n", - "#\n", - "solver.Solve()\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", + " 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", + " print()\n", + " print('WallTime:', solver.WallTime())\n", + " if sol == 'CBC':\n", + " print('iterations:', solver.Iterations())\n", + "\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/discrete_tomography.ipynb b/examples/notebook/contrib/discrete_tomography.ipynb index deb2351015..87414228af 100644 --- a/examples/notebook/contrib/discrete_tomography.ipynb +++ b/examples/notebook/contrib/discrete_tomography.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Discrete tomography in Google CP Solver.\n", "\n", @@ -127,79 +112,89 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(row_sums=\"\", col_sums=\"\"):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", - "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", + " 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", + "\n", "def print_solution(x, rows, cols, row_sums, col_sums):\n", " print(\" \", end=\" \")\n", " for j in range(cols):\n", @@ -227,6 +222,14 @@ "\n", " return [row_sums, col_sums]\n", "\n", + "\n", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " print(\"Problem instance from\", file)\n", + " [row_sums, col_sums] = read_problem(file)\n", + " main(row_sums, col_sums)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/divisible_by_9_through_1.ipynb b/examples/notebook/contrib/divisible_by_9_through_1.ipynb index 8843650145..62ba85887c 100644 --- a/examples/notebook/contrib/divisible_by_9_through_1.ipynb +++ b/examples/notebook/contrib/divisible_by_9_through_1.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Divisible by 9 through 1 puzzle in Google CP Solver.\n", "\n", @@ -125,8 +110,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -179,64 +172,78 @@ " s == solver.Sum([(base**(tlen - i - 1)) * t[i] for i in range(tlen)]))\n", "\n", "\n", + "def main(base=10):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Divisible by 9 through 1\")\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", + " # data\n", + " m = base**(base - 1) - 1\n", + " n = base - 1\n", "\n", - "digits_str = \"_0123456789ABCDEFGH\"\n", + " digits_str = \"_0123456789ABCDEFGH\"\n", "\n", - "print(\"base:\", base)\n", + " print(\"base:\", base)\n", "\n", - "# declare variables\n", + " # declare variables\n", "\n", - "# the digits\n", - "x = [solver.IntVar(1, base - 1, \"x[%i]\" % i) for i in range(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", + " # 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", + " # 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", + " 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", + " # 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", + " 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", + " 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", - "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" + "max_base = 16\n", + "if len(sys.argv) > 1:\n", + " base = int(sys.argv[1])\n", + " if base > max_base:\n", + " print(\"Sorry, max allowed base is %i. Setting base to %i...\" %\n", + " (max_base, default_base))\n", + " base = default_base\n", + "main(base)\n", + "\n", + "# for base in range(2, 17):\n", + "# print\n", + "# main(base)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/dudeney.ipynb b/examples/notebook/contrib/dudeney.ipynb index 3355dc6173..962e845c5d 100644 --- a/examples/notebook/contrib/dudeney.ipynb +++ b/examples/notebook/contrib/dudeney.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -114,6 +114,8 @@ " print('#fails:', solver.Failures())\n", " print('time:', solver.WallTime(), 'ms')\n", "\n", + "\n", + "dudeney(6)\n", "\n" ] } diff --git a/examples/notebook/contrib/einav_puzzle.ipynb b/examples/notebook/contrib/einav_puzzle.ipynb index 89a2736f7c..eb428a2f81 100644 --- a/examples/notebook/contrib/einav_puzzle.ipynb +++ b/examples/notebook/contrib/einav_puzzle.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " A programming puzzle from Einav in Google CP Solver.\n", "\n", @@ -136,137 +121,149 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Einav puzzle')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Einav puzzle')\n", "\n", - "#\n", - "# data\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", + " # 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", + " # 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", + " #\n", + " # variables\n", + " #\n", + " x = {}\n", " for i in range(rows):\n", " for j in range(cols):\n", - " print('%3i' % x[i, j].Value(), end=' ')\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", - "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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/einav_puzzle2.ipynb b/examples/notebook/contrib/einav_puzzle2.ipynb index 88a74fbedb..24ef4e4f1c 100644 --- a/examples/notebook/contrib/einav_puzzle2.ipynb +++ b/examples/notebook/contrib/einav_puzzle2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " A programming puzzle from Einav in Google CP Solver.\n", "\n", @@ -137,130 +122,142 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Einav puzzle\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Einav puzzle\")\n", "\n", - "#\n", - "# data\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", + " # 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", + " # 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", + " #\n", + " # variables\n", + " #\n", + " x = {}\n", " for i in range(rows):\n", " for j in range(cols):\n", - " print(\"%3i\" % x[i, j].Value(), end=\" \")\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", - "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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/eq10.ipynb b/examples/notebook/contrib/eq10.ipynb index a8ec97ecf1..fe395c42cb 100644 --- a/examples/notebook/contrib/eq10.ipynb +++ b/examples/notebook/contrib/eq10.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Eq 10 in Google CP Solver.\n", "\n", @@ -100,79 +85,91 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Eq 10\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Eq 10\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 7\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", + " # 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", + " # 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", + " 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", + " 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", + " 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", + " 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", + " 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", + " 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", + " 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", + " 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", + " 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", + " # search and result\n", + " #\n", + " db = solver.Phase(X, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n", "\n", - "solver.NewSearch(db)\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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/eq20.ipynb b/examples/notebook/contrib/eq20.ipynb index 5b7ba9fbc0..63cf9ab870 100644 --- a/examples/notebook/contrib/eq20.ipynb +++ b/examples/notebook/contrib/eq20.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Eq 20 in Google CP Solver.\n", "\n", @@ -100,90 +85,102 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Eq 20\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Eq 20\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 7\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", + " # 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", + " # 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", + " # search and result\n", + " #\n", + " db = solver.Phase(X, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE)\n", "\n", - "solver.NewSearch(db)\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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/fill_a_pix.ipynb b/examples/notebook/contrib/fill_a_pix.ipynb index 251f2e3df9..ff5d85ba58 100644 --- a/examples/notebook/contrib/fill_a_pix.ipynb +++ b/examples/notebook/contrib/fill_a_pix.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Fill-a-Pix problem in Google CP Solver.\n", "\n", @@ -124,8 +109,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -142,88 +135,90 @@ "]\n", "\n", "\n", + "def main(puzzle='', n=''):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Fill-a-Pix')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Fill-a-Pix')\n", "\n", - "#\n", - "# data\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", + " # 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", + " # 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", + " # print problem instance\n", + " print('Problem:')\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", + " if puzzle[i][j] == X:\n", + " sys.stdout.write('.')\n", " else:\n", - " row[j] = '#'\n", - " print(''.join(row))\n", + " sys.stdout.write(str(puzzle[i][j]))\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", + " # 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", + "#\n", + "def read_problem(file):\n", " f = open(file, 'r')\n", " n = int(f.readline())\n", " puzzle = []\n", @@ -239,6 +234,14 @@ " puzzle.append(row)\n", " return [puzzle, n]\n", "\n", + "\n", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " print('Problem instance from', file)\n", + " [puzzle, n] = read_problem(file)\n", + " main(puzzle, n)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/furniture_moving.ipynb b/examples/notebook/contrib/furniture_moving.ipynb index 7c6f456a4e..1f4cfa2d80 100644 --- a/examples/notebook/contrib/furniture_moving.ipynb +++ b/examples/notebook/contrib/furniture_moving.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Moving furnitures (scheduling) problem in Google CP Solver.\n", "\n", @@ -109,8 +94,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -155,95 +148,99 @@ " solver.Add(b <= sum(r))\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Furniture moving\")\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", + " # 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", + " # 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", + " # 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", + " # 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", + " solver.Add(end_time == solver.Max(end_times))\n", "\n", - "my_cumulative(solver, start_times, duration, demand, num_resources)\n", + " my_cumulative(solver, start_times, duration, demand, num_resources)\n", "\n", - "#\n", - "# Some extra constraints to play with\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", - "#\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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/futoshiki.ipynb b/examples/notebook/contrib/futoshiki.ipynb index 13a67f3d22..7eb52f5695 100644 --- a/examples/notebook/contrib/futoshiki.ipynb +++ b/examples/notebook/contrib/futoshiki.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Futoshiki problem in Google CP Solver.\n", "\n", @@ -118,77 +103,86 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(values, lt):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Futoshiki problem\")\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", + " # 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", + " #\n", + " # variables\n", + " #\n", + " field = {}\n", " for i in RANGE:\n", " for j in RANGE:\n", - " print(field[i, j].Value(), end=\" \")\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", - " print()\n", "\n", - "solver.EndSearch()\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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", "\n", "\n", "#\n", @@ -202,7 +196,8 @@ "#\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", + "#\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", @@ -226,6 +221,11 @@ "# 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", + "print(\"Problem 1\")\n", + "main(values1, lt1)\n", + "print(\"\\nProblem 2\")\n", + "main(values2, lt2)\n", "\n" ] } diff --git a/examples/notebook/contrib/game_theory_taha.ipynb b/examples/notebook/contrib/game_theory_taha.ipynb index a3e80c0624..8aded34f82 100644 --- a/examples/notebook/contrib/game_theory_taha.ipynb +++ b/examples/notebook/contrib/game_theory_taha.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Game theory in Google or-tools.\n", "\n", @@ -97,87 +82,106 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " 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", + " 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", + " solver.Add(solver.Sum(x1) == 1)\n", "\n", - "objective = solver.Maximize(v)\n", + " objective = solver.Maximize(v)\n", "\n", - "solver.Solve()\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", + " 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", + " # 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", + " 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", + " 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", + " solver.Add(solver.Sum(x2) == 1)\n", "\n", - "objective = solver.Minimize(v2)\n", + " objective = solver.Minimize(v2)\n", "\n", - "solver.Solve()\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", + " 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", + " print()\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " print('iterations:', solver.Iterations())\n", + " print()\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/grocery.ipynb b/examples/notebook/contrib/grocery.ipynb index 5a14cb6ee2..30648cf0b0 100644 --- a/examples/notebook/contrib/grocery.ipynb +++ b/examples/notebook/contrib/grocery.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Grocery problem in Google CP Solver.\n", "\n", @@ -109,58 +94,70 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "from functools import reduce\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Grocery\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Grocery\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 4\n", - "c = 711\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", + " # 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", + " # 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", + " # 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", + " # 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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/hidato.ipynb b/examples/notebook/contrib/hidato.ipynb index b7fbd8f22d..7a0a43755c 100644 --- a/examples/notebook/contrib/hidato.ipynb +++ b/examples/notebook/contrib/hidato.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Hidato puzzle in Google CP Solver.\n", "\n", " http://www.shockwave.com/gamelanding/hidato.jsp\n", @@ -113,154 +98,164 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"hidato\")\n", + "def main(r, c):\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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", - "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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", @@ -275,6 +270,16 @@ " print(\"% 2s\" % game[i][j], end=\" \")\n", " print(\"\")\n", "\n", + "\n", + "# data\n", + "r = 3\n", + "c = r\n", + "if len(sys.argv) > 1:\n", + " r = int(sys.argv[1])\n", + " c = r\n", + "if len(sys.argv) > 2:\n", + " c = int(sys.argv[2])\n", + "main(r, c)\n", "\n" ] } diff --git a/examples/notebook/contrib/just_forgotten.ipynb b/examples/notebook/contrib/just_forgotten.ipynb index b56edb6839..9a91d0e5fc 100644 --- a/examples/notebook/contrib/just_forgotten.ipynb +++ b/examples/notebook/contrib/just_forgotten.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Just forgotten puzzle (Enigma 1517) in Google CP Solver.\n", "\n", @@ -118,70 +103,82 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Just forgotten\")\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", + " # 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", + " # 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", + " # 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", + " 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", + " # search and result\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\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", + " 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", - " check = \" \"\n", - " if a[i][j] == xval[j]:\n", - " check = \"!\"\n", - " print(\"%i%s\" % (a[i][j], check), end=\" \")\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", - "print()\n", "\n", - "solver.EndSearch()\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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/kakuro.ipynb b/examples/notebook/contrib/kakuro.ipynb index 57be57c271..4e77d46cde 100644 --- a/examples/notebook/contrib/kakuro.ipynb +++ b/examples/notebook/contrib/kakuro.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Kakuru puzzle in Google CP Solver.\n", "\n", @@ -128,8 +113,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -152,101 +145,105 @@ " solver.Add(solver.Sum([x[i[0] - 1, i[1] - 1] for i in cc]) == res)\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Kakuro\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Kakuro\")\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "# size of matrix\n", - "n = 7\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", + " # 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", + " 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", + " # 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", + " # 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", + " # the set\n", + " x = {}\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", + " 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", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/kenken2.ipynb b/examples/notebook/contrib/kenken2.ipynb index 216627cf73..3939c64cd5 100644 --- a/examples/notebook/contrib/kenken2.ipynb +++ b/examples/notebook/contrib/kenken2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " KenKen puzzle in Google CP Solver.\n", "\n", @@ -129,8 +114,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -182,86 +175,90 @@ " solver.Add(this_sum + this_prod >= 1)\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"KenKen\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"KenKen\")\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "# size of matrix\n", - "n = 6\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", + " # 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", + " # 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", + " num_p = len(problem)\n", "\n", - "#\n", - "# variables\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", + " # the set\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(x[i, j].Value(), end=\" \")\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", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/killer_sudoku.ipynb b/examples/notebook/contrib/killer_sudoku.ipynb index 33ce388d3a..543c1d4404 100644 --- a/examples/notebook/contrib/killer_sudoku.ipynb +++ b/examples/notebook/contrib/killer_sudoku.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Killer Sudoku in Google CP Solver.\n", "\n", @@ -141,8 +126,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -162,101 +155,105 @@ " solver.Add(solver.AllDifferent(cage))\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Killer Sudoku\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Killer Sudoku\")\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "# size of matrix\n", - "n = 9\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", + " # 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", + " # 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", + " # 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", + " # the set\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(x[i, j].Value(), end=\" \")\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", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/knapsack_cp.ipynb b/examples/notebook/contrib/knapsack_cp.ipynb index 0105384cf9..13443e9359 100644 --- a/examples/notebook/contrib/knapsack_cp.ipynb +++ b/examples/notebook/contrib/knapsack_cp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Knapsack problem in Google CP Solver.\n", "\n", @@ -95,8 +80,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", @@ -110,55 +103,59 @@ " return [x, z]\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"knapsack_cp\")\n", + "def main(values, weights, 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", + " #\n", + " # data\n", + " #\n", + " print(\"values:\", values)\n", + " print(\"weights:\", weights)\n", + " print(\"n:\", 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", + " # 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", "\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", + "main(values, weights, n)\n", "\n" ] } diff --git a/examples/notebook/contrib/knapsack_mip.ipynb b/examples/notebook/contrib/knapsack_mip.ipynb index 0870953e53..4758f28f28 100644 --- a/examples/notebook/contrib/knapsack_mip.ipynb +++ b/examples/notebook/contrib/knapsack_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Knapsack problem using MIP in Google or-tools.\n", "\n", @@ -95,80 +80,100 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " # 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", + " # 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", + " 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", + " 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", + " # 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", + " # 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", + " # 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", + " # objective\n", + " objective = solver.Maximize(z)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\n", - "print('z: ', int(solver.Objective().Value()))\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", + " 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", + " print()\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " if sol == 'CBC':\n", + " print('iterations:', solver.Iterations())\n", + "\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/labeled_dice.ipynb b/examples/notebook/contrib/labeled_dice.ipynb index 4fb7122e78..6208d613fb 100644 --- a/examples/notebook/contrib/labeled_dice.ipynb +++ b/examples/notebook/contrib/labeled_dice.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Labeled dice problem in Google CP Solver.\n", "\n", @@ -120,90 +105,102 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Labeled dice\")\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", + " # 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", + " 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", + " # 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", + " # 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", + " # the letters in a word must be on a different die\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", + " 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", - "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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/langford.ipynb b/examples/notebook/contrib/langford.ipynb index dba4bac16a..7c49bb3583 100644 --- a/examples/notebook/contrib/langford.ipynb +++ b/examples/notebook/contrib/langford.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Langford's number problem in Google CP Solver.\n", "\n", @@ -117,66 +102,83 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(k=8, num_sol=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Langford\")\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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " 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", + " 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", - "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" + "num_sol = 0\n", + "if len(sys.argv) > 1:\n", + " k = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " num_sol = int(sys.argv[2])\n", + "\n", + "main(k, num_sol)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/least_diff.ipynb b/examples/notebook/contrib/least_diff.ipynb index 7008125b85..716a38bba4 100644 --- a/examples/notebook/contrib/least_diff.ipynb +++ b/examples/notebook/contrib/least_diff.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Least diff problem in Google CP Solver.\n", "\n", @@ -110,79 +95,91 @@ "\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", + " http://www.hakank.org/google_cp_solver/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Least diff\")\n", + "def main(unused_argv):\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", + " # 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", + " 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", + " 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", + " 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", + " # constraints\n", + " #\n", + " solver.Add(diff > 0)\n", + " solver.Add(solver.AllDifferent(letters))\n", "\n", - "# objective\n", - "objective = solver.Minimize(diff, 1)\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", + " # 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", + " # 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", + " # 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", + " 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", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/least_square.ipynb b/examples/notebook/contrib/least_square.ipynb index b05cd7cd33..515e399803 100644 --- a/examples/notebook/contrib/least_square.ipynb +++ b/examples/notebook/contrib/least_square.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Least square optimization problem in Google or-tools.\n", "\n", @@ -98,69 +83,89 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " objective = solver.Minimize(z)\n", "\n", - "solver.Solve()\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", + " print()\n", + " print('z = ', solver.Objective().Value())\n", + " for i in range(p + 1):\n", + " print(a[i].SolutionValue(), end=' ')\n", + " print()\n", + "\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/lectures.ipynb b/examples/notebook/contrib/lectures.ipynb index c46e884b65..398fb2c756 100644 --- a/examples/notebook/contrib/lectures.ipynb +++ b/examples/notebook/contrib/lectures.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Lectures problem in Google CP Solver.\n", "\n", @@ -117,80 +102,92 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Lectures')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Lectures')\n", "\n", - "#\n", - "# data\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", + " # 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", + " # number of nodes\n", + " n = 6\n", "\n", - "# number of edges\n", - "edges = len(g)\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " print('num_solutions:', num_solutions)\n", + " print('failures:', solver.Failures())\n", + " print('branches:', solver.Branches())\n", + " print('WallTime:', solver.WallTime(), 'ms')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/magic_sequence_sat.ipynb b/examples/notebook/contrib/magic_sequence_sat.ipynb index a81378c3fe..24f188fa5e 100644 --- a/examples/notebook/contrib/magic_sequence_sat.ipynb +++ b/examples/notebook/contrib/magic_sequence_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,15 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Solve the magic sequence problem with the CP-SAT solver.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,52 +83,41 @@ "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", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", - "\"\"\"Magic sequence problem.\"\"\"\n", - "n = 100\n", - "values = range(n)\n", + "def main():\n", + " \"\"\"Magic sequence problem.\"\"\"\n", + " n = 100\n", + " values = range(n)\n", "\n", - "model = cp_model.CpModel()\n", + " model = cp_model.CpModel()\n", "\n", - "x = [model.NewIntVar(0, n, 'x%i' % i) for i in values]\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", + " 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", + " # 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", + " 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", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/magic_square.ipynb b/examples/notebook/contrib/magic_square.ipynb index 7283183323..396b6a649e 100644 --- a/examples/notebook/contrib/magic_square.ipynb +++ b/examples/notebook/contrib/magic_square.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Magic squares in Google CP Solver.\n", "\n", @@ -95,88 +80,105 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(n, limit):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"n-queens\")\n", "\n", - "#\n", - "# data\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", + " #\n", + " # declare variables\n", + " #\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(\"%2i\" % x[(i, j)].Value(), end=\" \")\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", - " num_solutions += 1\n", - " if num_solutions > limit:\n", - " break\n", - "solver.EndSearch()\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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" + "limit=100\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " limit = int(sys.argv[2])\n", + "\n", + "main(n, limit)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/magic_square_and_cards.ipynb b/examples/notebook/contrib/magic_square_and_cards.ipynb index 8bfdf7e799..b52852ac4e 100644 --- a/examples/notebook/contrib/magic_square_and_cards.ipynb +++ b/examples/notebook/contrib/magic_square_and_cards.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Magic squares and cards problem in Google CP Solver.\n", "\n", @@ -101,83 +86,97 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(n=3):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"n-queens\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "# n = 3\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", + " #\n", + " # declare variables\n", + " #\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(x[(i, j)].Value(), end=\" \")\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", - " num_solutions += 1\n", - "solver.EndSearch()\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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" + "n = 3\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/magic_square_mip.ipynb b/examples/notebook/contrib/magic_square_mip.ipynb index 9b2dfa7c10..a02fcb4923 100644 --- a/examples/notebook/contrib/magic_square_mip.ipynb +++ b/examples/notebook/contrib/magic_square_mip.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Magic square (integer programming) in Google or-tools.\n", "\n", @@ -115,8 +100,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", @@ -127,135 +120,154 @@ "#\n", "\n", "\n", + "def main(n=3, sol='CBC', use_output_matrix=0):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print('Solver: ', sol)\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", + " # 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", + " # data\n", + " #\n", + " print('n = ', n)\n", "\n", - "# range_n = range(1, n+1)\n", - "range_n = list(range(0, 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 * n\n", + " range_N = list(range(1, N + 1))\n", "\n", - "#\n", - "# variables\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", + " # 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", - " for k in range_N:\n", - " x[i, j, k] = solver.IntVar(0, 1, 'x[%i,%i,%i]' % (i, j, k))\n", + " solver.Add(\n", + " solver.Sum([k * x[i, j, k] for i in range_n for k in range_N]) == s)\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", + " # # the sum in the diagonal must be the magic sum\n", " solver.Add(\n", - " solver.Sum([k * x[i, j, k] for j in range_n for k in range_N]) == s)\n", + " solver.Sum([k * x[i, i, k] for i 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", + " # # 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", - "# # 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", + " # 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", - "# # 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", + " # solution and search\n", + " #\n", + " solver.Solve()\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", + "\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", - " print(\n", - " sum([int(k * x[i, j, k].SolutionValue()) for k in range_N]),\n", - " ' ',\n", - " end=' ')\n", - " print()\n", + " for k in range_N:\n", + " print(int(x[i, j, k].SolutionValue()), 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", + " print()\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " if sol == 'CBC':\n", + " print('iterations:', solver.Iterations())\n", "\n", - "print()\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "if sol == 'CBC':\n", - " print('iterations:', solver.Iterations())\n", + "\n", + "n = 3\n", + "sol = 'CBC'\n", + "use_output_matrix = 0\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "\n", + "if len(sys.argv) > 2:\n", + " sol = sys.argv[2]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "if len(sys.argv) > 3:\n", + " use_output_matrix = int(sys.argv[3])\n", + "\n", + "main(n, sol, use_output_matrix)\n", "\n" ] } diff --git a/examples/notebook/contrib/map.ipynb b/examples/notebook/contrib/map.ipynb index f6c0750b63..c20e3657f7 100644 --- a/examples/notebook/contrib/map.ipynb +++ b/examples/notebook/contrib/map.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Map coloring problem in Google CP Solver.\n", "\n", @@ -106,72 +91,84 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Map coloring\")\n", + "def main():\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", + " # 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 = 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " 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", + " else:\n", + " print(\"No solutions found\")\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/marathon2.ipynb b/examples/notebook/contrib/marathon2.ipynb index a37f4dbcb5..1946e366a4 100644 --- a/examples/notebook/contrib/marathon2.ipynb +++ b/examples/notebook/contrib/marathon2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Marathon puzzle in Google CP Solver.\n", "\n", @@ -120,88 +105,100 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Marathon')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Marathon')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 6\n", + " #\n", + " # data\n", + " #\n", + " n = 6\n", "\n", - "runners_str = [\n", - " 'Dominique', 'Ignace', 'Naren', 'Olivier', 'Philippe', 'Pascal'\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", + " # 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", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(runners))\n", "\n", - "# a: Olivier not last\n", - "solver.Add(Olivier != 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", + " print('num_solutions:', num_solutions)\n", + " print('failures:', solver.Failures())\n", + " print('branches:', solver.Branches())\n", + " print('WallTime:', solver.WallTime(), 'ms')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/max_flow_taha.ipynb b/examples/notebook/contrib/max_flow_taha.ipynb index 4bb3a6a88d..ec10b80b5b 100644 --- a/examples/notebook/contrib/max_flow_taha.ipynb +++ b/examples/notebook/contrib/max_flow_taha.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Max flow problem in Google CP Solver.\n", "\n", @@ -101,93 +86,105 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Max flow problem, Taha')\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", + " # data\n", + " #\n", + " n = 5\n", + " start = 0\n", + " end = n - 1\n", "\n", - "nodes = list(range(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", + " # 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", + " #\n", + " # declare variables\n", + " #\n", + " x = {}\n", " for i in nodes:\n", " for j in nodes:\n", - " print('%2i' % x[i, j].Value(), end=' ')\n", - " print()\n", - " print()\n", + " x[i, j] = solver.IntVar(0, c[i][j], 'x[%i,%i]' % (i, j))\n", "\n", - "print('num_solutions:', num_solutions)\n", - "print('failures:', solver.Failures())\n", - "print('branches:', solver.Branches())\n", - "print('WallTime:', solver.WallTime(), 'ms')\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", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/max_flow_winston1.ipynb b/examples/notebook/contrib/max_flow_winston1.ipynb index 8fc44b8975..a125d72c9d 100644 --- a/examples/notebook/contrib/max_flow_winston1.ipynb +++ b/examples/notebook/contrib/max_flow_winston1.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Max flow problem in Google CP Solver.\n", "\n", @@ -101,111 +86,123 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Max flow problem, Winston')\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", + " # 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", + " # 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", + " # 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", + " num_arcs = len(arcs)\n", "\n", - "# capacities\n", - "cap = [2, 3, 3, 4, 2, 1, 100]\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", + " # convert arcs to matrix\n", + " # for sanity checking below\n", + " mat = {}\n", " for i in nodes:\n", " for j in nodes:\n", - " print(flow[i, j].Value(), end=' ')\n", - " print()\n", - " print()\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", - "print('num_solutions:', num_solutions)\n", - "print('failures:', solver.Failures())\n", - "print('branches:', solver.Branches())\n", - "print('WallTime:', solver.WallTime(), 'ms')\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", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/minesweeper.ipynb b/examples/notebook/contrib/minesweeper.ipynb index c17d676425..71e44fd03e 100644 --- a/examples/notebook/contrib/minesweeper.ipynb +++ b/examples/notebook/contrib/minesweeper.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Minesweeper in Google CP Solver.\n", "\n", @@ -136,8 +121,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -150,115 +143,117 @@ " [0, 1, X, 4, X, X, X, 3], [0, 1, 2, X, 2, 3, X, 2]]\n", "\n", "\n", + "def main(game=\"\", r=\"\", c=\"\"):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Minesweeper\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Minesweeper\")\n", "\n", - "#\n", - "# data\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", + " # 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", + " # 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", + " 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 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", - "\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", + " # 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", + "#\n", + "def read_problem(file):\n", " f = open(file, \"r\")\n", " rows = int(f.readline())\n", " cols = int(f.readline())\n", @@ -292,6 +287,15 @@ " print(game[i][j], end=\" \")\n", " print(\"\")\n", "\n", + "\n", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " print(\"Problem instance from\", file)\n", + " [game, rows, cols] = read_problem(file)\n", + " # print_game(game, rows, cols)\n", + " main(game, rows, cols)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/mr_smith.ipynb b/examples/notebook/contrib/mr_smith.ipynb index fdfa62b6d0..57181af7ff 100644 --- a/examples/notebook/contrib/mr_smith.ipynb +++ b/examples/notebook/contrib/mr_smith.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Mr Smith in Google CP Solver.\n", "\n", @@ -120,74 +105,86 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Mr Smith problem')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Mr Smith problem')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 5\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", + " # 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", + " # constraints\n", + " #\n", "\n", - "#\n", - "# I've kept the MiniZinc constraints for clarity\n", - "# and debugging.\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # solution and search\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\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", + " 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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/nonogram_default_search.ipynb b/examples/notebook/contrib/nonogram_default_search.ipynb index d276045155..3577069cfd 100644 --- a/examples/notebook/contrib/nonogram_default_search.ipynb +++ b/examples/notebook/contrib/nonogram_default_search.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Nonogram (Painting by numbers) in Google CP Solver.\n", "\n", @@ -113,8 +98,16 @@ " 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", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -175,81 +168,82 @@ " accepting_states))\n", "\n", "\n", + "def main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Nonogram')\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", + " #\n", + " # variables\n", + " #\n", + " board = {}\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", + " 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", - " board_label.append(board[i, j])\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", + " #\n", + " # constraints\n", + " #\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", + " 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(' ', '-' * 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", + " 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", @@ -257,7 +251,8 @@ "#\n", "# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n", "# The lambda picture\n", - "#rows = 12\n", + "#\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", @@ -266,6 +261,11 @@ "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", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " exec(compile(open(file).read(), file, 'exec'))\n", + "main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules)\n", "\n" ] } diff --git a/examples/notebook/contrib/nonogram_regular.ipynb b/examples/notebook/contrib/nonogram_regular.ipynb index d1343f7b87..28c44be4ed 100644 --- a/examples/notebook/contrib/nonogram_regular.ipynb +++ b/examples/notebook/contrib/nonogram_regular.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Nonogram (Painting by numbers) in Google CP Solver.\n", "\n", @@ -139,8 +124,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -300,82 +293,83 @@ " accepting_states)\n", "\n", "\n", + "def main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Regular test')\n", "\n", - "#\n", - "# data\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", + " #\n", + " # variables\n", + " #\n", + " board = {}\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", + " 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", - " board_label.append(board[i, j])\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", + " #\n", + " # constraints\n", + " #\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", + " 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(' ', '-' * 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", + " 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", @@ -383,7 +377,8 @@ "#\n", "# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n", "# The lambda picture\n", - "#rows = 12\n", + "#\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", @@ -392,6 +387,11 @@ "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", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " exec(compile(open(file).read(), file, 'exec'))\n", + "main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules)\n", "\n" ] } diff --git a/examples/notebook/contrib/nonogram_table.ipynb b/examples/notebook/contrib/nonogram_table.ipynb index 980f14fdcf..01e08fe2fd 100644 --- a/examples/notebook/contrib/nonogram_table.ipynb +++ b/examples/notebook/contrib/nonogram_table.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Nonogram (Painting by numbers) in Google CP Solver.\n", "\n", @@ -139,8 +124,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -296,82 +289,83 @@ " accepting_states)\n", "\n", "\n", + "def main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Regular test')\n", "\n", - "#\n", - "# data\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", + " #\n", + " # variables\n", + " #\n", + " board = {}\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", + " 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", - " board_label.append(board[i, j])\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", + " #\n", + " # constraints\n", + " #\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", + " 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(' ', '-' * 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", + " 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", @@ -379,7 +373,8 @@ "#\n", "# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n", "# The lambda picture\n", - "#rows = 12\n", + "#\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", @@ -388,6 +383,11 @@ "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", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " exec(compile(open(file).read(), file, 'exec'))\n", + "main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules)\n", "\n" ] } diff --git a/examples/notebook/contrib/nonogram_table2.ipynb b/examples/notebook/contrib/nonogram_table2.ipynb index 90a04becef..4b19c14d53 100644 --- a/examples/notebook/contrib/nonogram_table2.ipynb +++ b/examples/notebook/contrib/nonogram_table2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Nonogram (Painting by numbers) in Google CP Solver.\n", "\n", @@ -139,8 +124,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -201,77 +194,78 @@ " accepting_states))\n", "\n", "\n", + "def main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\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", + " #\n", + " # variables\n", + " #\n", + " board = {}\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", + " 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", - " board_label.append(board[i, j])\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", + " #\n", + " # constraints\n", + " #\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", + " 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(' ', '-' * 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", + " 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", @@ -279,7 +273,8 @@ "#\n", "# From http://twan.home.fmf.nl/blog/haskell/Nonograms.details\n", "# The lambda picture\n", - "#rows = 12\n", + "#\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", @@ -288,6 +283,11 @@ "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", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " exec(compile(open(file).read(), file, 'exec'))\n", + "main(rows, row_rule_len, row_rules, cols, col_rule_len, col_rules)\n", "\n" ] } diff --git a/examples/notebook/contrib/nontransitive_dice.ipynb b/examples/notebook/contrib/nontransitive_dice.ipynb index 137582ea1e..d0a359db22 100644 --- a/examples/notebook/contrib/nontransitive_dice.ipynb +++ b/examples/notebook/contrib/nontransitive_dice.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Nontransitive dice in Google CP Solver.\n", "\n", @@ -140,141 +125,160 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(m=3, n=6, minimize_val=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Nontransitive dice\")\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", + " # data\n", + " #\n", + " print(\"number of dice:\", m)\n", + " print(\"number of sides:\", n)\n", "\n", - "#\n", - "# declare variables\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", + " 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", + " 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", - " print(comp[(i, j)].Value(), end=\" \")\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", - " print(\"counts:\", [counts[i].Value() for i in range(n * 2 + 1)])\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", - " 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" + "minimize_val = 0 # Minimizing max value (0: no, 1: yes)\n", + "if len(sys.argv) > 1:\n", + " m = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " n = int(sys.argv[2])\n", + "if len(sys.argv) > 3:\n", + " minimize_val = int(sys.argv[3])\n", + "\n", + "main(m, n, minimize_val)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/nqueens.ipynb b/examples/notebook/contrib/nqueens.ipynb index 5a45b6cdbf..c2d5248083 100644 --- a/examples/notebook/contrib/nqueens.ipynb +++ b/examples/notebook/contrib/nqueens.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " n-queens problem in Google CP Solver.\n", "\n", @@ -95,77 +80,89 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(n=8):\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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " # 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", + " 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", + " 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", - " print()\n", - " print(\"num_solutions:\", num_solutions)\n", - " print(\"failures:\", solver.Failures())\n", - " print(\"branches:\", solver.Branches())\n", - " print(\"WallTime:\", solver.WallTime())\n", + " else:\n", + " print(\"No solutions found\")\n", "\n", - "else:\n", - " print(\"No solutions found\")\n", "\n", - "n = 8\n" + "n = 8\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/nqueens2.ipynb b/examples/notebook/contrib/nqueens2.ipynb index 07e08840fe..8dc1f76e20 100644 --- a/examples/notebook/contrib/nqueens2.ipynb +++ b/examples/notebook/contrib/nqueens2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " n-queens problem in Google CP Solver.\n", "\n", @@ -98,76 +83,90 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(n=8):\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", + " # 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", + " # 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", - "# db: DecisionBuilder\n", - "db = solver.Phase(\n", - " [q[i] for i in range(n)],\n", - " # solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n", - " solver.ASSIGN_CENTER_VALUE)\n", - "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " qval = [q[i].Value() for i in range(n)]\n", - " print(\"q:\", qval)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(q))\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", + " 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", + " # db: DecisionBuilder\n", + " db = solver.Phase(\n", + " [q[i] for i in range(n)],\n", + " # solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n", + " solver.ASSIGN_CENTER_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " qval = [q[i].Value() 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", + " num_solutions += 1\n", + " solver.EndSearch()\n", + "\n", " print()\n", - " num_solutions += 1\n", - "solver.EndSearch()\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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 = 8\n" + "n = 8\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/nqueens3.ipynb b/examples/notebook/contrib/nqueens3.ipynb index 2061aaf47d..db71d282c6 100644 --- a/examples/notebook/contrib/nqueens3.ipynb +++ b/examples/notebook/contrib/nqueens3.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " n-queens problem in Google CP Solver.\n", "\n", @@ -100,71 +85,96 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + "def main(n=8, num_sol=0, print_sol=1):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"n-queens\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"n:\", n)\n", - "print(\"num_sol:\", num_sol)\n", - "print(\"print_sol:\", print_sol)\n", + " #\n", + " # data\n", + " #\n", + " print(\"n:\", n)\n", + " print(\"num_sol:\", num_sol)\n", + " print(\"print_sol:\", print_sol)\n", "\n", - "# declare variables\n", - "q = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(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", - "solver.Add(solver.AllDifferent([q[i] + i for i in range(n)]))\n", - "solver.Add(solver.AllDifferent([q[i] - i for i in range(n)]))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(q))\n", + " solver.Add(solver.AllDifferent([q[i] + i for i in range(n)]))\n", + " solver.Add(solver.AllDifferent([q[i] - i for i in range(n)]))\n", "\n", - "# symmetry breaking\n", - "# solver.Add(q[0] == 0)\n", + " # symmetry breaking\n", + " # solver.Add(q[0] == 0)\n", "\n", - "#\n", - "# search\n", - "#\n", + " #\n", + " # search\n", + " #\n", "\n", - "db = solver.Phase(q, solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n", - " solver.ASSIGN_CENTER_VALUE)\n", + " db = solver.Phase(q, solver.CHOOSE_MIN_SIZE_LOWEST_MAX,\n", + " solver.ASSIGN_CENTER_VALUE)\n", "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " if print_sol:\n", - " qval = [q[i].Value() 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", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " if print_sol:\n", + " qval = [q[i].Value() 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", - " print()\n", - " num_solutions += 1\n", - " if num_sol > 0 and num_solutions >= num_sol:\n", - " break\n", + " num_solutions += 1\n", + " if num_sol > 0 and num_solutions >= num_sol:\n", + " break\n", "\n", - "solver.EndSearch()\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", - "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 = 8\n", "num_sol = 0\n", - "print_sol = 1\n" + "print_sol = 1\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " num_sol = int(sys.argv[2])\n", + "if len(sys.argv) > 3:\n", + " print_sol = int(sys.argv[3])\n", + "\n", + "main(n, num_sol, print_sol)\n", + "\n", + "# print_sol = False\n", + "# show_all = False\n", + "# for n in range(1000,1001):\n", + "# print\n", + "# main(n, num_sol, print_sol)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/nurse_rostering.ipynb b/examples/notebook/contrib/nurse_rostering.ipynb index 46464a4003..29507f47c7 100644 --- a/examples/notebook/contrib/nurse_rostering.ipynb +++ b/examples/notebook/contrib/nurse_rostering.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Nurse rostering in Google CP Solver.\n", "\n", @@ -102,8 +87,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "from collections import defaultdict\n", "\n", @@ -177,164 +170,168 @@ " a[i + 1] == solver.Element(d2_flatten, ((a[i]) * S) + (x[i] - 1)))\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Nurse rostering using regular')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Nurse rostering using regular')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "# Note: If you change num_nurses or num_days,\n", - "# please also change the constraints\n", - "# on nurse_stat and/or day_stat.\n", - "num_nurses = 7\n", - "num_days = 14\n", + " # Note: If you change num_nurses or num_days,\n", + " # please also change the constraints\n", + " # on nurse_stat and/or day_stat.\n", + " num_nurses = 7\n", + " num_days = 14\n", "\n", - "day_shift = 1\n", - "night_shift = 2\n", - "off_shift = 3\n", - "shifts = [day_shift, night_shift, off_shift]\n", + " day_shift = 1\n", + " night_shift = 2\n", + " off_shift = 3\n", + " shifts = [day_shift, night_shift, off_shift]\n", "\n", - "# the DFA (for regular)\n", - "n_states = 6\n", - "input_max = 3\n", - "initial_state = 1 # 0 is for the failing state\n", - "accepting_states = [1, 2, 3, 4, 5, 6]\n", + " # the DFA (for regular)\n", + " n_states = 6\n", + " input_max = 3\n", + " initial_state = 1 # 0 is for the failing state\n", + " accepting_states = [1, 2, 3, 4, 5, 6]\n", "\n", - "transition_fn = [\n", - " # d,n,o\n", - " [2, 3, 1], # state 1\n", - " [4, 4, 1], # state 2\n", - " [4, 5, 1], # state 3\n", - " [6, 6, 1], # state 4\n", - " [6, 0, 1], # state 5\n", - " [0, 0, 1] # state 6\n", - "]\n", - "\n", - "days = ['d', 'n', 'o'] # for presentation\n", - "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = {}\n", - "for i in range(num_nurses):\n", - " for j in range(num_days):\n", - " x[i, j] = solver.IntVar(shifts, 'x[%i,%i]' % (i, j))\n", - "\n", - "x_flat = [x[i, j] for i in range(num_nurses) for j in range(num_days)]\n", - "\n", - "# summary of the nurses\n", - "nurse_stat = [\n", - " solver.IntVar(0, num_days, 'nurse_stat[%i]' % i)\n", - " for i in range(num_nurses)\n", - "]\n", - "\n", - "# summary of the shifts per day\n", - "day_stat = {}\n", - "for i in range(num_days):\n", - " for j in shifts:\n", - " day_stat[i, j] = solver.IntVar(0, num_nurses, 'day_stat[%i,%i]' % (i, j))\n", - "\n", - "day_stat_flat = [day_stat[i, j] for i in range(num_days) for j in shifts]\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "for i in range(num_nurses):\n", - " reg_input = [x[i, j] for j in range(num_days)]\n", - " regular(reg_input, n_states, input_max, transition_fn, initial_state,\n", - " accepting_states)\n", - "\n", - "#\n", - "# Statistics and constraints for each nurse\n", - "#\n", - "for i in range(num_nurses):\n", - " # number of worked days (day or night shift)\n", - " b = [\n", - " solver.IsEqualCstVar(x[i, j], day_shift) + solver.IsEqualCstVar(\n", - " x[i, j], night_shift) for j in range(num_days)\n", + " transition_fn = [\n", + " # d,n,o\n", + " [2, 3, 1], # state 1\n", + " [4, 4, 1], # state 2\n", + " [4, 5, 1], # state 3\n", + " [6, 6, 1], # state 4\n", + " [6, 0, 1], # state 5\n", + " [0, 0, 1] # state 6\n", " ]\n", - " solver.Add(nurse_stat[i] == solver.Sum(b))\n", "\n", - " # Each nurse must work between 7 and 10\n", - " # days during this period\n", - " solver.Add(nurse_stat[i] >= 7)\n", - " solver.Add(nurse_stat[i] <= 10)\n", - "\n", - "#\n", - "# Statistics and constraints for each day\n", - "#\n", - "for j in range(num_days):\n", - " for t in shifts:\n", - " b = [solver.IsEqualCstVar(x[i, j], t) for i in range(num_nurses)]\n", - " solver.Add(day_stat[j, t] == solver.Sum(b))\n", + " days = ['d', 'n', 'o'] # for presentation\n", "\n", " #\n", - " # Some constraints for this day:\n", + " # declare variables\n", " #\n", - " # Note: We have a strict requirements of\n", - " # the number of shifts.\n", - " # Using atleast constraints is much harder\n", - " # in this model.\n", - " #\n", - " if j % 7 == 5 or j % 7 == 6:\n", - " # special constraints for the weekends\n", - " solver.Add(day_stat[j, day_shift] == 2)\n", - " solver.Add(day_stat[j, night_shift] == 1)\n", - " solver.Add(day_stat[j, off_shift] == 4)\n", - " else:\n", - " # workdays:\n", - "\n", - " # - exactly 3 on day shift\n", - " solver.Add(day_stat[j, day_shift] == 3)\n", - " # - exactly 2 on night\n", - " solver.Add(day_stat[j, night_shift] == 2)\n", - " # - exactly 1 off duty\n", - " solver.Add(day_stat[j, off_shift] == 2)\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(day_stat_flat + x_flat + nurse_stat,\n", - " 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", - "\n", + " x = {}\n", " for i in range(num_nurses):\n", - " print('Nurse%i: ' % i, end=' ')\n", - " this_day_stat = defaultdict(int)\n", " for j in range(num_days):\n", - " d = days[x[i, j].Value() - 1]\n", - " this_day_stat[d] += 1\n", - " print(d, end=' ')\n", - " print(\n", - " ' day_stat:', [(d, this_day_stat[d]) for d in this_day_stat], end=' ')\n", - " print('total:', nurse_stat[i].Value(), 'workdays')\n", - " print()\n", + " x[i, j] = solver.IntVar(shifts, 'x[%i,%i]' % (i, j))\n", "\n", - " print('Statistics per day:')\n", + " x_flat = [x[i, j] for i in range(num_nurses) for j in range(num_days)]\n", + "\n", + " # summary of the nurses\n", + " nurse_stat = [\n", + " solver.IntVar(0, num_days, 'nurse_stat[%i]' % i)\n", + " for i in range(num_nurses)\n", + " ]\n", + "\n", + " # summary of the shifts per day\n", + " day_stat = {}\n", + " for i in range(num_days):\n", + " for j in shifts:\n", + " day_stat[i, j] = solver.IntVar(0, num_nurses, 'day_stat[%i,%i]' % (i, j))\n", + "\n", + " day_stat_flat = [day_stat[i, j] for i in range(num_days) for j in shifts]\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + " for i in range(num_nurses):\n", + " reg_input = [x[i, j] for j in range(num_days)]\n", + " regular(reg_input, n_states, input_max, transition_fn, initial_state,\n", + " accepting_states)\n", + "\n", + " #\n", + " # Statistics and constraints for each nurse\n", + " #\n", + " for i in range(num_nurses):\n", + " # number of worked days (day or night shift)\n", + " b = [\n", + " solver.IsEqualCstVar(x[i, j], day_shift) + solver.IsEqualCstVar(\n", + " x[i, j], night_shift) for j in range(num_days)\n", + " ]\n", + " solver.Add(nurse_stat[i] == solver.Sum(b))\n", + "\n", + " # Each nurse must work between 7 and 10\n", + " # days during this period\n", + " solver.Add(nurse_stat[i] >= 7)\n", + " solver.Add(nurse_stat[i] <= 10)\n", + "\n", + " #\n", + " # Statistics and constraints for each day\n", + " #\n", " for j in range(num_days):\n", - " print('Day%2i: ' % j, end=' ')\n", " for t in shifts:\n", - " print(day_stat[j, t].Value(), end=' ')\n", + " b = [solver.IsEqualCstVar(x[i, j], t) for i in range(num_nurses)]\n", + " solver.Add(day_stat[j, t] == solver.Sum(b))\n", + "\n", + " #\n", + " # Some constraints for this day:\n", + " #\n", + " # Note: We have a strict requirements of\n", + " # the number of shifts.\n", + " # Using atleast constraints is much harder\n", + " # in this model.\n", + " #\n", + " if j % 7 == 5 or j % 7 == 6:\n", + " # special constraints for the weekends\n", + " solver.Add(day_stat[j, day_shift] == 2)\n", + " solver.Add(day_stat[j, night_shift] == 1)\n", + " solver.Add(day_stat[j, off_shift] == 4)\n", + " else:\n", + " # workdays:\n", + "\n", + " # - exactly 3 on day shift\n", + " solver.Add(day_stat[j, day_shift] == 3)\n", + " # - exactly 2 on night\n", + " solver.Add(day_stat[j, night_shift] == 2)\n", + " # - exactly 1 off duty\n", + " solver.Add(day_stat[j, off_shift] == 2)\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(day_stat_flat + x_flat + nurse_stat,\n", + " 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", + "\n", + " for i in range(num_nurses):\n", + " print('Nurse%i: ' % i, end=' ')\n", + " this_day_stat = defaultdict(int)\n", + " for j in range(num_days):\n", + " d = days[x[i, j].Value() - 1]\n", + " this_day_stat[d] += 1\n", + " print(d, end=' ')\n", + " print(\n", + " ' day_stat:', [(d, this_day_stat[d]) for d in this_day_stat], end=' ')\n", + " print('total:', nurse_stat[i].Value(), 'workdays')\n", " print()\n", + "\n", + " print('Statistics per day:')\n", + " for j in range(num_days):\n", + " print('Day%2i: ' % j, end=' ')\n", + " for t in shifts:\n", + " print(day_stat[j, t].Value(), end=' ')\n", + " print()\n", + " print()\n", + "\n", + " # We just show 2 solutions\n", + " if num_solutions >= 2:\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", - " # We just show 2 solutions\n", - " if num_solutions >= 2:\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/nurses_cp.ipynb b/examples/notebook/contrib/nurses_cp.ipynb index 99f306405a..e1c722cfb9 100644 --- a/examples/notebook/contrib/nurses_cp.ipynb +++ b/examples/notebook/contrib/nurses_cp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -78,175 +78,179 @@ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Creates the solver.\n", - "solver = pywrapcp.Solver(\"schedule_shifts\")\n", + "def main():\n", + " # Creates the solver.\n", + " solver = pywrapcp.Solver(\"schedule_shifts\")\n", "\n", - "num_nurses = 4\n", - "num_shifts = 4 # Nurse assigned to shift 0 means not working that day.\n", - "num_days = 7\n", - "# [START]\n", - "# Create shift variables.\n", - "shifts = {}\n", - "\n", - "for j in range(num_nurses):\n", - " for i in range(num_days):\n", - " shifts[(j, i)] = solver.IntVar(0, num_shifts - 1,\n", - " \"shifts(%i,%i)\" % (j, i))\n", - "shifts_flat = [\n", - " shifts[(j, i)] for j in range(num_nurses) for i in range(num_days)\n", - "]\n", - "\n", - "# Create nurse variables.\n", - "nurses = {}\n", - "\n", - "for j in range(num_shifts):\n", - " for i in range(num_days):\n", - " nurses[(j, i)] = solver.IntVar(0, num_nurses - 1,\n", - " \"shift%d day%d\" % (j, i))\n", - "# Set relationships between shifts and nurses.\n", - "for day in range(num_days):\n", - " nurses_for_day = [nurses[(j, day)] for j in range(num_shifts)]\n", + " num_nurses = 4\n", + " num_shifts = 4 # Nurse assigned to shift 0 means not working that day.\n", + " num_days = 7\n", + " # [START]\n", + " # Create shift variables.\n", + " shifts = {}\n", "\n", " for j in range(num_nurses):\n", - " s = shifts[(j, day)]\n", - " solver.Add(s.IndexOf(nurses_for_day) == j)\n", - "# Make assignments different on each day\n", - "for i in range(num_days):\n", - " solver.Add(solver.AllDifferent([shifts[(j, i)] for j in range(num_nurses)]))\n", - " solver.Add(solver.AllDifferent([nurses[(j, i)] for j in range(num_shifts)]))\n", - "# Each nurse works 5 or 6 days in a week.\n", - "for j in range(num_nurses):\n", - " solver.Add(solver.Sum([shifts[(j, i)] > 0 for i in range(num_days)]) >= 5)\n", - " solver.Add(solver.Sum([shifts[(j, i)] > 0 for i in range(num_days)]) <= 6)\n", - "# Create works_shift variables. works_shift[(i, j)] is True if nurse\n", - "# i works shift j at least once during the week.\n", - "works_shift = {}\n", + " for i in range(num_days):\n", + " shifts[(j, i)] = solver.IntVar(0, num_shifts - 1,\n", + " \"shifts(%i,%i)\" % (j, i))\n", + " shifts_flat = [\n", + " shifts[(j, i)] for j in range(num_nurses) for i in range(num_days)\n", + " ]\n", + "\n", + " # Create nurse variables.\n", + " nurses = {}\n", "\n", - "for i in range(num_nurses):\n", " for j in range(num_shifts):\n", - " works_shift[(i, j)] = solver.BoolVar(\"nurse%d shift%d\" % (i, j))\n", + " for i in range(num_days):\n", + " nurses[(j, i)] = solver.IntVar(0, num_nurses - 1,\n", + " \"shift%d day%d\" % (j, i))\n", + " # Set relationships between shifts and nurses.\n", + " for day in range(num_days):\n", + " nurses_for_day = [nurses[(j, day)] for j in range(num_shifts)]\n", "\n", - "for i in range(num_nurses):\n", - " for j in range(num_shifts):\n", - " solver.Add(works_shift[(\n", - " i, j)] == solver.Max([shifts[(i, k)] == j for k in range(num_days)]))\n", - "\n", - "# For each shift (other than 0), at most 2 nurses are assigned to that shift\n", - "# during the week.\n", - "for j in range(1, num_shifts):\n", - " solver.Add(\n", - " solver.Sum([works_shift[(i, j)] for i in range(num_nurses)]) <= 2)\n", - "# If s nurses works shifts 2 or 3 on, he must also work that shift the previous\n", - "# day or the following day.\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 0)] == nurses[(2,\n", - " 1)], nurses[(2,\n", - " 1)] == nurses[(2,\n", - " 2)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 1)] == nurses[(2,\n", - " 2)], nurses[(2,\n", - " 2)] == nurses[(2,\n", - " 3)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 2)] == nurses[(2,\n", - " 3)], nurses[(2,\n", - " 3)] == nurses[(2,\n", - " 4)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 3)] == nurses[(2,\n", - " 4)], nurses[(2,\n", - " 4)] == nurses[(2,\n", - " 5)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 4)] == nurses[(2,\n", - " 5)], nurses[(2,\n", - " 5)] == nurses[(2,\n", - " 6)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 5)] == nurses[(2,\n", - " 6)], nurses[(2,\n", - " 6)] == nurses[(2,\n", - " 0)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(2,\n", - " 6)] == nurses[(2,\n", - " 0)], nurses[(2,\n", - " 0)] == nurses[(2,\n", - " 1)]) == 1)\n", - "\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 0)] == nurses[(3,\n", - " 1)], nurses[(3,\n", - " 1)] == nurses[(3,\n", - " 2)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 1)] == nurses[(3,\n", - " 2)], nurses[(3,\n", - " 2)] == nurses[(3,\n", - " 3)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 2)] == nurses[(3,\n", - " 3)], nurses[(3,\n", - " 3)] == nurses[(3,\n", - " 4)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 3)] == nurses[(3,\n", - " 4)], nurses[(3,\n", - " 4)] == nurses[(3,\n", - " 5)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 4)] == nurses[(3,\n", - " 5)], nurses[(3,\n", - " 5)] == nurses[(3,\n", - " 6)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 5)] == nurses[(3,\n", - " 6)], nurses[(3,\n", - " 6)] == nurses[(3,\n", - " 0)]) == 1)\n", - "solver.Add(\n", - " solver.Max(nurses[(3,\n", - " 6)] == nurses[(3,\n", - " 0)], nurses[(3,\n", - " 0)] == nurses[(3,\n", - " 1)]) == 1)\n", - "# Create the decision builder.\n", - "db = solver.Phase(shifts_flat, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE)\n", - "# Create the solution collector.\n", - "solution = solver.Assignment()\n", - "solution.Add(shifts_flat)\n", - "collector = solver.AllSolutionCollector(solution)\n", - "\n", - "solver.Solve(db, [collector])\n", - "print(\"Solutions found:\", collector.SolutionCount())\n", - "print(\"Time:\", solver.WallTime(), \"ms\")\n", - "print()\n", - "# Display a few solutions picked at random.\n", - "a_few_solutions = [859, 2034, 5091, 7003]\n", - "\n", - "for sol in a_few_solutions:\n", - " print(\"Solution number\", sol, \"\\n\")\n", - "\n", - " for i in range(num_days):\n", - " print(\"Day\", i)\n", " for j in range(num_nurses):\n", - " print(\"Nurse\", j, \"assigned to task\",\n", - " collector.Value(sol, shifts[(j, i)]))\n", - " print()\n", + " s = shifts[(j, day)]\n", + " solver.Add(s.IndexOf(nurses_for_day) == j)\n", + " # Make assignments different on each day\n", + " for i in range(num_days):\n", + " solver.Add(solver.AllDifferent([shifts[(j, i)] for j in range(num_nurses)]))\n", + " solver.Add(solver.AllDifferent([nurses[(j, i)] for j in range(num_shifts)]))\n", + " # Each nurse works 5 or 6 days in a week.\n", + " for j in range(num_nurses):\n", + " solver.Add(solver.Sum([shifts[(j, i)] > 0 for i in range(num_days)]) >= 5)\n", + " solver.Add(solver.Sum([shifts[(j, i)] > 0 for i in range(num_days)]) <= 6)\n", + " # Create works_shift variables. works_shift[(i, j)] is True if nurse\n", + " # i works shift j at least once during the week.\n", + " works_shift = {}\n", + "\n", + " for i in range(num_nurses):\n", + " for j in range(num_shifts):\n", + " works_shift[(i, j)] = solver.BoolVar(\"nurse%d shift%d\" % (i, j))\n", + "\n", + " for i in range(num_nurses):\n", + " for j in range(num_shifts):\n", + " solver.Add(works_shift[(\n", + " i, j)] == solver.Max([shifts[(i, k)] == j for k in range(num_days)]))\n", + "\n", + " # For each shift (other than 0), at most 2 nurses are assigned to that shift\n", + " # during the week.\n", + " for j in range(1, num_shifts):\n", + " solver.Add(\n", + " solver.Sum([works_shift[(i, j)] for i in range(num_nurses)]) <= 2)\n", + " # If s nurses works shifts 2 or 3 on, he must also work that shift the previous\n", + " # day or the following day.\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 0)] == nurses[(2,\n", + " 1)], nurses[(2,\n", + " 1)] == nurses[(2,\n", + " 2)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 1)] == nurses[(2,\n", + " 2)], nurses[(2,\n", + " 2)] == nurses[(2,\n", + " 3)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 2)] == nurses[(2,\n", + " 3)], nurses[(2,\n", + " 3)] == nurses[(2,\n", + " 4)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 3)] == nurses[(2,\n", + " 4)], nurses[(2,\n", + " 4)] == nurses[(2,\n", + " 5)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 4)] == nurses[(2,\n", + " 5)], nurses[(2,\n", + " 5)] == nurses[(2,\n", + " 6)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 5)] == nurses[(2,\n", + " 6)], nurses[(2,\n", + " 6)] == nurses[(2,\n", + " 0)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(2,\n", + " 6)] == nurses[(2,\n", + " 0)], nurses[(2,\n", + " 0)] == nurses[(2,\n", + " 1)]) == 1)\n", + "\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 0)] == nurses[(3,\n", + " 1)], nurses[(3,\n", + " 1)] == nurses[(3,\n", + " 2)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 1)] == nurses[(3,\n", + " 2)], nurses[(3,\n", + " 2)] == nurses[(3,\n", + " 3)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 2)] == nurses[(3,\n", + " 3)], nurses[(3,\n", + " 3)] == nurses[(3,\n", + " 4)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 3)] == nurses[(3,\n", + " 4)], nurses[(3,\n", + " 4)] == nurses[(3,\n", + " 5)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 4)] == nurses[(3,\n", + " 5)], nurses[(3,\n", + " 5)] == nurses[(3,\n", + " 6)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 5)] == nurses[(3,\n", + " 6)], nurses[(3,\n", + " 6)] == nurses[(3,\n", + " 0)]) == 1)\n", + " solver.Add(\n", + " solver.Max(nurses[(3,\n", + " 6)] == nurses[(3,\n", + " 0)], nurses[(3,\n", + " 0)] == nurses[(3,\n", + " 1)]) == 1)\n", + " # Create the decision builder.\n", + " db = solver.Phase(shifts_flat, solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE)\n", + " # Create the solution collector.\n", + " solution = solver.Assignment()\n", + " solution.Add(shifts_flat)\n", + " collector = solver.AllSolutionCollector(solution)\n", + "\n", + " solver.Solve(db, [collector])\n", + " print(\"Solutions found:\", collector.SolutionCount())\n", + " print(\"Time:\", solver.WallTime(), \"ms\")\n", + " print()\n", + " # Display a few solutions picked at random.\n", + " a_few_solutions = [859, 2034, 5091, 7003]\n", + "\n", + " for sol in a_few_solutions:\n", + " print(\"Solution number\", sol, \"\\n\")\n", + "\n", + " for i in range(num_days):\n", + " print(\"Day\", i)\n", + " for j in range(num_nurses):\n", + " print(\"Nurse\", j, \"assigned to task\",\n", + " collector.Value(sol, shifts[(j, i)]))\n", + " print()\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/olympic.ipynb b/examples/notebook/contrib/olympic.ipynb index a0696ae737..4c60823bc5 100644 --- a/examples/notebook/contrib/olympic.ipynb +++ b/examples/notebook/contrib/olympic.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Olympic puzzle in Google CP Solver.\n", "\n", @@ -129,8 +114,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -139,51 +132,55 @@ " solver.Add(z == abs(x - y))\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Olympic')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Olympic')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 10\n", + " #\n", + " # data\n", + " #\n", + " n = 10\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "Vars = [solver.IntVar(1, n, 'Vars[%i]' % i) for i in range(n)]\n", - "X1, X2, X3, X4, X5, X6, X7, X8, X9, X10 = Vars\n", + " #\n", + " # declare variables\n", + " #\n", + " Vars = [solver.IntVar(1, n, 'Vars[%i]' % i) for i in range(n)]\n", + " X1, X2, X3, X4, X5, X6, X7, X8, X9, X10 = Vars\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(Vars))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(Vars))\n", "\n", - "solver.Add(X1 == 3)\n", - "minus(solver, X2, X3, X1)\n", - "minus(solver, X4, X5, X2)\n", - "minus(solver, X5, X6, X3)\n", - "minus(solver, X7, X8, X4)\n", - "minus(solver, X8, X9, X5)\n", - "minus(solver, X9, X10, X6)\n", + " solver.Add(X1 == 3)\n", + " minus(solver, X2, X3, X1)\n", + " minus(solver, X4, X5, X2)\n", + " minus(solver, X5, X6, X3)\n", + " minus(solver, X7, X8, X4)\n", + " minus(solver, X8, X9, X5)\n", + " minus(solver, X9, X10, X6)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(Vars, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(Vars, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('Vars:', [Vars[i].Value() for i in range(n)])\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('Vars:', [Vars[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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/organize_day.ipynb b/examples/notebook/contrib/organize_day.ipynb index bc9a4b5e08..f32ea638f3 100644 --- a/examples/notebook/contrib/organize_day.ipynb +++ b/examples/notebook/contrib/organize_day.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Organizing a day in Google CP Solver.\n", "\n", @@ -105,8 +90,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -121,68 +114,72 @@ " solver.Add(b1 + b2 >= 1)\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Organizing a day')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Organizing a day')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 4\n", + " #\n", + " # data\n", + " #\n", + " n = 4\n", "\n", - "tasks = list(range(n))\n", - "work, mail, shop, bank = tasks\n", - "durations = [4, 1, 2, 1]\n", + " tasks = list(range(n))\n", + " work, mail, shop, bank = tasks\n", + " durations = [4, 1, 2, 1]\n", "\n", - "# task [i,0] must be finished before task [i,1]\n", - "before_tasks = [[bank, shop], [mail, work]]\n", + " # task [i,0] must be finished before task [i,1]\n", + " before_tasks = [[bank, shop], [mail, work]]\n", "\n", - "# the valid times of the day\n", - "begin = 9\n", - "end = 17\n", + " # the valid times of the day\n", + " begin = 9\n", + " end = 17\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "begins = [solver.IntVar(begin, end, 'begins[%i]% % i') for i in tasks]\n", - "ends = [solver.IntVar(begin, end, 'ends[%i]% % i') for i in tasks]\n", + " #\n", + " # declare variables\n", + " #\n", + " begins = [solver.IntVar(begin, end, 'begins[%i]% % i') for i in tasks]\n", + " ends = [solver.IntVar(begin, end, 'ends[%i]% % i') for i in tasks]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "for i in tasks:\n", - " solver.Add(ends[i] == begins[i] + durations[i])\n", + " #\n", + " # constraints\n", + " #\n", + " for i in tasks:\n", + " solver.Add(ends[i] == begins[i] + durations[i])\n", "\n", - "for i in tasks:\n", - " for j in tasks:\n", - " if i < j:\n", - " no_overlap(solver, begins[i], durations[i], begins[j], durations[j])\n", + " for i in tasks:\n", + " for j in tasks:\n", + " if i < j:\n", + " no_overlap(solver, begins[i], durations[i], begins[j], durations[j])\n", "\n", - "# specific constraints\n", - "for (before, after) in before_tasks:\n", - " solver.Add(ends[before] <= begins[after])\n", + " # specific constraints\n", + " for (before, after) in before_tasks:\n", + " solver.Add(ends[before] <= begins[after])\n", "\n", - "solver.Add(begins[work] >= 11)\n", + " solver.Add(begins[work] >= 11)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(begins + ends, solver.INT_VAR_DEFAULT,\n", - " solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(begins + ends, solver.INT_VAR_DEFAULT,\n", + " solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('begins:', [begins[i].Value() for i in tasks])\n", - " print('ends:', [ends[i].Value() for i in tasks])\n", - " print()\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('begins:', [begins[i].Value() for i in tasks])\n", + " print('ends:', [ends[i].Value() for i in tasks])\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", + " print('num_solutions:', num_solutions)\n", + " print('failures:', solver.Failures())\n", + " print('branches:', solver.Branches())\n", + " print('WallTime:', solver.WallTime(), 'ms')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/p_median.ipynb b/examples/notebook/contrib/p_median.ipynb index 83a52e7615..0cb3a2fddc 100644 --- a/examples/notebook/contrib/p_median.ipynb +++ b/examples/notebook/contrib/p_median.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " P-median problem in Google CP Solver.\n", "\n", @@ -107,89 +92,101 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('P-median problem')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('P-median problem')\n", "\n", - "#\n", - "# data\n", - "#\n", - "p = 2\n", + " #\n", + " # data\n", + " #\n", + " p = 2\n", "\n", - "num_customers = 4\n", - "customers = list(range(num_customers))\n", - "Albert, Bob, Chris, Daniel = customers\n", - "num_warehouses = 3\n", - "warehouses = list(range(num_warehouses))\n", - "Santa_Clara, San_Jose, Berkeley = warehouses\n", + " num_customers = 4\n", + " customers = list(range(num_customers))\n", + " Albert, Bob, Chris, Daniel = customers\n", + " num_warehouses = 3\n", + " warehouses = list(range(num_warehouses))\n", + " Santa_Clara, San_Jose, Berkeley = warehouses\n", "\n", - "demand = [100, 80, 80, 70]\n", - "distance = [[2, 10, 50], [2, 10, 52], [50, 60, 3], [40, 60, 1]]\n", + " demand = [100, 80, 80, 70]\n", + " distance = [[2, 10, 50], [2, 10, 52], [50, 60, 3], [40, 60, 1]]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "open = [solver.IntVar(warehouses, 'open[%i]% % i') for w in warehouses]\n", - "ship = {}\n", - "for c in customers:\n", - " for w in warehouses:\n", - " ship[c, w] = solver.IntVar(0, 1, 'ship[%i,%i]' % (c, w))\n", - "ship_flat = [ship[c, w] for c in customers for w in warehouses]\n", - "\n", - "z = solver.IntVar(0, 1000, 'z')\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "z_sum = solver.Sum([\n", - " demand[c] * distance[c][w] * ship[c, w]\n", - " for c in customers\n", - " for w in warehouses\n", - "])\n", - "solver.Add(z == z_sum)\n", - "\n", - "for c in customers:\n", - " s = solver.Sum([ship[c, w] for w in warehouses])\n", - " solver.Add(s == 1)\n", - "\n", - "solver.Add(solver.Sum(open) == p)\n", - "\n", - "for c in customers:\n", - " for w in warehouses:\n", - " solver.Add(ship[c, w] <= open[w])\n", - "\n", - "# objective\n", - "objective = solver.Minimize(z, 1)\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(open + ship_flat, solver.INT_VAR_DEFAULT,\n", - " solver.INT_VALUE_DEFAULT)\n", - "\n", - "solver.NewSearch(db, [objective])\n", - "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('z:', z.Value())\n", - " print('open:', [open[w].Value() for w in warehouses])\n", + " #\n", + " # declare variables\n", + " #\n", + " open = [solver.IntVar(warehouses, 'open[%i]% % i') for w in warehouses]\n", + " ship = {}\n", " for c in customers:\n", " for w in warehouses:\n", - " print(ship[c, w].Value(), end=' ')\n", - " print()\n", - " print()\n", + " ship[c, w] = solver.IntVar(0, 1, 'ship[%i,%i]' % (c, w))\n", + " ship_flat = [ship[c, w] for c in customers for w in warehouses]\n", "\n", - "print('num_solutions:', num_solutions)\n", - "print('failures:', solver.Failures())\n", - "print('branches:', solver.Branches())\n", - "print('WallTime:', solver.WallTime(), 'ms')\n", + " z = solver.IntVar(0, 1000, 'z')\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + " z_sum = solver.Sum([\n", + " demand[c] * distance[c][w] * ship[c, w]\n", + " for c in customers\n", + " for w in warehouses\n", + " ])\n", + " solver.Add(z == z_sum)\n", + "\n", + " for c in customers:\n", + " s = solver.Sum([ship[c, w] for w in warehouses])\n", + " solver.Add(s == 1)\n", + "\n", + " solver.Add(solver.Sum(open) == p)\n", + "\n", + " for c in customers:\n", + " for w in warehouses:\n", + " solver.Add(ship[c, w] <= open[w])\n", + "\n", + " # objective\n", + " objective = solver.Minimize(z, 1)\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(open + ship_flat, solver.INT_VAR_DEFAULT,\n", + " solver.INT_VALUE_DEFAULT)\n", + "\n", + " solver.NewSearch(db, [objective])\n", + "\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('z:', z.Value())\n", + " print('open:', [open[w].Value() for w in warehouses])\n", + " for c in customers:\n", + " for w in warehouses:\n", + " print(ship[c, w].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", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/pandigital_numbers.ipynb b/examples/notebook/contrib/pandigital_numbers.ipynb index 4a664e48f9..9e69bc8094 100644 --- a/examples/notebook/contrib/pandigital_numbers.ipynb +++ b/examples/notebook/contrib/pandigital_numbers.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Pandigital numbers in Google CP Solver.\n", "\n", @@ -134,8 +119,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -151,72 +144,74 @@ " s == solver.Sum([(base**(tlen - i - 1)) * t[i] for i in range(tlen)]))\n", "\n", "\n", + "def main(base=10, start=1, len1=1, len2=4):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Pandigital numbers\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Pandigital numbers\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "max_d = base - 1\n", - "x_len = max_d + 1 - start\n", - "max_num = base**4 - 1\n", + " #\n", + " # data\n", + " #\n", + " max_d = base - 1\n", + " x_len = max_d + 1 - start\n", + " max_num = base**4 - 1\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "num1 = solver.IntVar(0, max_num, \"num1\")\n", - "num2 = solver.IntVar(0, max_num, \"num2\")\n", - "res = solver.IntVar(0, max_num, \"res\")\n", + " #\n", + " # declare variables\n", + " #\n", + " num1 = solver.IntVar(0, max_num, \"num1\")\n", + " num2 = solver.IntVar(0, max_num, \"num2\")\n", + " res = solver.IntVar(0, max_num, \"res\")\n", "\n", - "x = [solver.IntVar(start, max_d, \"x[%i]\" % i) for i in range(x_len)]\n", + " x = [solver.IntVar(start, max_d, \"x[%i]\" % i) for i in range(x_len)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", "\n", - "toNum(solver, [x[i] for i in range(len1)], num1, base)\n", - "toNum(solver, [x[i] for i in range(len1, len1 + len2)], num2, base)\n", - "toNum(solver, [x[i] for i in range(len1 + len2, x_len)], res, base)\n", + " toNum(solver, [x[i] for i in range(len1)], num1, base)\n", + " toNum(solver, [x[i] for i in range(len1, len1 + len2)], num2, base)\n", + " toNum(solver, [x[i] for i in range(len1 + len2, x_len)], res, base)\n", "\n", - "solver.Add(num1 * num2 == res)\n", + " solver.Add(num1 * num2 == res)\n", "\n", - "# no number must start with 0\n", - "solver.Add(x[0] > 0)\n", - "solver.Add(x[len1] > 0)\n", - "solver.Add(x[len1 + len2] > 0)\n", + " # no number must start with 0\n", + " solver.Add(x[0] > 0)\n", + " solver.Add(x[len1] > 0)\n", + " solver.Add(x[len1 + len2] > 0)\n", "\n", - "# symmetry breaking\n", - "solver.Add(num1 < num2)\n", + " # symmetry breaking\n", + " solver.Add(num1 < num2)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.Add(num1)\n", - "solution.Add(num2)\n", - "solution.Add(res)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.Add(num1)\n", + " solution.Add(num2)\n", + " solution.Add(res)\n", "\n", - "db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", + " db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "solutions = []\n", - "while solver.NextSolution():\n", - " print_solution([x[i].Value() for i in range(x_len)], len1, len2, x_len)\n", - " num_solutions += 1\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " solutions = []\n", + " while solver.NextSolution():\n", + " print_solution([x[i].Value() for i in range(x_len)], len1, len2, x_len)\n", + " num_solutions += 1\n", "\n", - "solver.EndSearch()\n", + " solver.EndSearch()\n", + "\n", + " if 0 and 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())\n", + " print()\n", "\n", - "if 0 and 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())\n", - " print()\n", "\n", "def print_solution(x, len1, len2, x_len):\n", " print(\"\".join([str(x[i]) for i in range(len1)]), \"*\", end=\" \")\n", @@ -225,7 +220,18 @@ "\n", "\n", "base = 10\n", - "start = 1\n" + "start = 1\n", + "if len(sys.argv) > 1:\n", + " base = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " start = int(sys.argv[2])\n", + "\n", + "x_len = base - 1 + 1 - start\n", + "for len1 in range(1 + (x_len)):\n", + " for len2 in range(1 + (x_len)):\n", + " if x_len > len1 + len2:\n", + " main(base, start, len1, len2)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/photo_problem.ipynb b/examples/notebook/contrib/photo_problem.ipynb index 8813d9175d..e6ce9d9adb 100644 --- a/examples/notebook/contrib/photo_problem.ipynb +++ b/examples/notebook/contrib/photo_problem.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Photo problem in Google CP Solver.\n", "\n", @@ -119,109 +104,123 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(show_all_max=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Photo problem\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Photo problem\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "persons = [\"Betty\", \"Chris\", \"Donald\", \"Fred\", \"Gary\", \"Mary\", \"Paul\"]\n", - "n = len(persons)\n", - "preferences = [\n", - " # 0 1 2 3 4 5 6\n", - " # B C D F G M P\n", - " [0, 0, 0, 0, 1, 1, 0], # Betty 0\n", - " [1, 0, 0, 0, 1, 0, 0], # Chris 1\n", - " [0, 0, 0, 0, 0, 0, 0], # Donald 2\n", - " [0, 0, 1, 0, 0, 1, 0], # Fred 3\n", - " [0, 0, 0, 0, 0, 0, 0], # Gary 4\n", - " [0, 0, 0, 0, 0, 0, 0], # Mary 5\n", - " [0, 0, 1, 1, 0, 0, 0] # Paul 6\n", - "]\n", + " #\n", + " # data\n", + " #\n", + " persons = [\"Betty\", \"Chris\", \"Donald\", \"Fred\", \"Gary\", \"Mary\", \"Paul\"]\n", + " n = len(persons)\n", + " preferences = [\n", + " # 0 1 2 3 4 5 6\n", + " # B C D F G M P\n", + " [0, 0, 0, 0, 1, 1, 0], # Betty 0\n", + " [1, 0, 0, 0, 1, 0, 0], # Chris 1\n", + " [0, 0, 0, 0, 0, 0, 0], # Donald 2\n", + " [0, 0, 1, 0, 0, 1, 0], # Fred 3\n", + " [0, 0, 0, 0, 0, 0, 0], # Gary 4\n", + " [0, 0, 0, 0, 0, 0, 0], # Mary 5\n", + " [0, 0, 1, 1, 0, 0, 0] # Paul 6\n", + " ]\n", "\n", - "print(\"\"\"Preferences:\n", - " 1. Betty wants to stand next to Gary and Mary.\n", - " 2. Chris wants to stand next to Betty and Gary.\n", - " 3. Fred wants to stand next to Mary and Donald.\n", - " 4. Paul wants to stand next to Fred and Donald.\n", - " \"\"\")\n", + " print(\"\"\"Preferences:\n", + " 1. Betty wants to stand next to Gary and Mary.\n", + " 2. Chris wants to stand next to Betty and Gary.\n", + " 3. Fred wants to stand next to Mary and Donald.\n", + " 4. Paul wants to stand next to Fred and Donald.\n", + " \"\"\")\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "positions = [solver.IntVar(0, n - 1, \"positions[%i]\" % i) for i in range(n)]\n", + " #\n", + " # declare variables\n", + " #\n", + " positions = [solver.IntVar(0, n - 1, \"positions[%i]\" % i) for i in range(n)]\n", "\n", - "# successful preferences\n", - "z = solver.IntVar(0, n * n, \"z\")\n", + " # successful preferences\n", + " z = solver.IntVar(0, n * n, \"z\")\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(positions))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(positions))\n", "\n", - "# calculate all the successful preferences\n", - "b = [\n", - " solver.IsEqualCstVar(abs(positions[i] - positions[j]), 1)\n", - " for i in range(n)\n", - " for j in range(n)\n", - " if preferences[i][j] == 1\n", - "]\n", - "solver.Add(z == solver.Sum(b))\n", + " # calculate all the successful preferences\n", + " b = [\n", + " solver.IsEqualCstVar(abs(positions[i] - positions[j]), 1)\n", + " for i in range(n)\n", + " for j in range(n)\n", + " if preferences[i][j] == 1\n", + " ]\n", + " solver.Add(z == solver.Sum(b))\n", "\n", - "#\n", - "# Symmetry breaking (from the Oz page):\n", - "# Fred is somewhere left of Betty\n", - "solver.Add(positions[3] < positions[0])\n", + " #\n", + " # Symmetry breaking (from the Oz page):\n", + " # Fred is somewhere left of Betty\n", + " solver.Add(positions[3] < positions[0])\n", "\n", - "# objective\n", - "objective = solver.Maximize(z, 1)\n", - "if show_all_max != 0:\n", - " print(\"Showing all maximum solutions (z == 6).\\n\")\n", - " solver.Add(z == 6)\n", + " # objective\n", + " objective = solver.Maximize(z, 1)\n", + " if show_all_max != 0:\n", + " print(\"Showing all maximum solutions (z == 6).\\n\")\n", + " solver.Add(z == 6)\n", "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(positions, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MAX_VALUE)\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(positions, solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MAX_VALUE)\n", "\n", - "if show_all_max == 0:\n", - " solver.NewSearch(db, [objective])\n", - "else:\n", - " solver.NewSearch(db)\n", + " if show_all_max == 0:\n", + " solver.NewSearch(db, [objective])\n", + " else:\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print(\"z:\", z.Value())\n", - " p = [positions[i].Value() for i in range(n)]\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print(\"z:\", z.Value())\n", + " p = [positions[i].Value() for i in range(n)]\n", + "\n", + " print(\" \".join(\n", + " [persons[j] for i in range(n) for j in range(n) if p[j] == i]))\n", + " print(\"Successful preferences:\")\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if preferences[i][j] == 1 and abs(p[i] - p[j]) == 1:\n", + " print(\"\\t\", persons[i], persons[j])\n", + " print()\n", + " num_solutions += 1\n", + "\n", + " solver.EndSearch()\n", "\n", - " print(\" \".join(\n", - " [persons[j] for i in range(n) for j in range(n) if p[j] == i]))\n", - " print(\"Successful preferences:\")\n", - " for i in range(n):\n", - " for j in range(n):\n", - " if preferences[i][j] == 1 and abs(p[i] - p[j]) == 1:\n", - " print(\"\\t\", persons[i], persons[j])\n", " print()\n", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", - "show_all_max = 0 # show all maximal solutions\n" + "show_all_max = 0 # show all maximal solutions\n", + "if len(sys.argv) > 1:\n", + " show_all_max = 1\n", + "main(show_all_max)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/place_number_puzzle.ipynb b/examples/notebook/contrib/place_number_puzzle.ipynb index f60dcfa74a..beef14b47e 100644 --- a/examples/notebook/contrib/place_number_puzzle.ipynb +++ b/examples/notebook/contrib/place_number_puzzle.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Place number puzzle Google CP Solver.\n", "\n", @@ -113,61 +98,73 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Place number\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Place number\")\n", "\n", - "# data\n", - "m = 32\n", - "n = 8\n", - "# Note: this is 1-based for compatibility (and lazyness)\n", - "graph = [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 5], [2, 6], [3, 2],\n", - " [3, 4], [3, 6], [3, 7], [4, 1], [4, 3], [4, 6], [4, 7], [5, 2],\n", - " [5, 3], [5, 6], [5, 8], [6, 2], [6, 3], [6, 4], [6, 5], [6, 7],\n", - " [6, 8], [7, 3], [7, 4], [7, 6], [7, 8], [8, 5], [8, 6], [8, 7]]\n", + " # data\n", + " m = 32\n", + " n = 8\n", + " # Note: this is 1-based for compatibility (and lazyness)\n", + " graph = [[1, 2], [1, 3], [1, 4], [2, 1], [2, 3], [2, 5], [2, 6], [3, 2],\n", + " [3, 4], [3, 6], [3, 7], [4, 1], [4, 3], [4, 6], [4, 7], [5, 2],\n", + " [5, 3], [5, 6], [5, 8], [6, 2], [6, 3], [6, 4], [6, 5], [6, 7],\n", + " [6, 8], [7, 3], [7, 4], [7, 6], [7, 8], [8, 5], [8, 6], [8, 7]]\n", "\n", - "# declare variables\n", - "x = [solver.IntVar(1, n, \"x%i\" % i) for i in range(n)]\n", + " # declare variables\n", + " x = [solver.IntVar(1, n, \"x%i\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", - "for i in range(m):\n", - " # Note: make 0-based\n", - " solver.Add(abs(x[graph[i][0] - 1] - x[graph[i][1] - 1]) > 1)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", + " for i in range(m):\n", + " # Note: make 0-based\n", + " solver.Add(abs(x[graph[i][0] - 1] - x[graph[i][1] - 1]) > 1)\n", "\n", - "# symmetry breaking\n", - "solver.Add(x[0] < x[n - 1])\n", + " # symmetry breaking\n", + " solver.Add(x[0] < x[n - 1])\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", "\n", - "collector = solver.AllSolutionCollector(solution)\n", + " collector = solver.AllSolutionCollector(solution)\n", "\n", - "solver.Solve(\n", - " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n", - " [collector])\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", + " 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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/post_office_problem2.ipynb b/examples/notebook/contrib/post_office_problem2.ipynb index a2ced90183..d2ef79a580 100644 --- a/examples/notebook/contrib/post_office_problem2.ipynb +++ b/examples/notebook/contrib/post_office_problem2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Post office problem in Google CP Solver.\n", "\n", @@ -127,77 +112,89 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Post office problem')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Post office problem')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "# days 0..6, monday 0\n", - "n = 7\n", - "days = list(range(n))\n", - "need = [17, 13, 15, 19, 14, 16, 11]\n", + " # days 0..6, monday 0\n", + " n = 7\n", + " days = list(range(n))\n", + " need = [17, 13, 15, 19, 14, 16, 11]\n", "\n", - "# Total cost for the 5 day schedule.\n", - "# Base cost per day is 100.\n", - "# Working saturday is 100 extra\n", - "# Working sunday is 200 extra.\n", - "cost = [500, 600, 800, 800, 800, 800, 700]\n", + " # Total cost for the 5 day schedule.\n", + " # Base cost per day is 100.\n", + " # Working saturday is 100 extra\n", + " # Working sunday is 200 extra.\n", + " cost = [500, 600, 800, 800, 800, 800, 700]\n", "\n", - "#\n", - "# variables\n", - "#\n", + " #\n", + " # variables\n", + " #\n", "\n", - "# No. of workers starting at day i\n", - "x = [solver.IntVar(0, 100, 'x[%i]' % i) for i in days]\n", + " # No. of workers starting at day i\n", + " x = [solver.IntVar(0, 100, 'x[%i]' % i) for i in days]\n", "\n", - "total_cost = solver.IntVar(0, 20000, 'total_cost')\n", - "num_workers = solver.IntVar(0, 100, 'num_workers')\n", + " total_cost = solver.IntVar(0, 20000, 'total_cost')\n", + " num_workers = solver.IntVar(0, 100, 'num_workers')\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(total_cost == solver.ScalProd(x, cost))\n", - "solver.Add(num_workers == solver.Sum(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(total_cost == solver.ScalProd(x, cost))\n", + " solver.Add(num_workers == solver.Sum(x))\n", "\n", - "for i in days:\n", - " s = solver.Sum(\n", - " [x[j] for j in days if j != (i + 5) % n and j != (i + 6) % n])\n", - " solver.Add(s >= need[i])\n", + " for i in days:\n", + " s = solver.Sum(\n", + " [x[j] for j in days if j != (i + 5) % n and j != (i + 6) % n])\n", + " solver.Add(s >= need[i])\n", "\n", - "# objective\n", - "objective = solver.Minimize(total_cost, 1)\n", + " # objective\n", + " objective = solver.Minimize(total_cost, 1)\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", + " # 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, [objective])\n", + " solver.NewSearch(db, [objective])\n", "\n", - "num_solutions = 0\n", + " num_solutions = 0\n", "\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('num_workers:', num_workers.Value())\n", - " print('total_cost:', total_cost.Value())\n", - " print('x:', [x[i].Value() for i in days])\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('num_workers:', num_workers.Value())\n", + " print('total_cost:', total_cost.Value())\n", + " print('x:', [x[i].Value() for i in days])\n", "\n", - "solver.EndSearch()\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/production.ipynb b/examples/notebook/contrib/production.ipynb index 19c3cf81ba..f0b6c648dd 100644 --- a/examples/notebook/contrib/production.ipynb +++ b/examples/notebook/contrib/production.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Production planning problem in Google or-tools.\n", "\n", @@ -95,90 +80,110 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol='CBC'):\n", "\n", - "# Create the solver.\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", + " # 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", - "#\n", - "# data\n", - "#\n", - "kluski = 0\n", - "capellini = 1\n", - "fettucine = 2\n", - "products = ['kluski', 'capellini', 'fettucine']\n", - "num_products = len(products)\n", + " #\n", + " # data\n", + " #\n", + " kluski = 0\n", + " capellini = 1\n", + " fettucine = 2\n", + " products = ['kluski', 'capellini', 'fettucine']\n", + " num_products = len(products)\n", "\n", - "flour = 0\n", - "eggs = 1\n", - "resources = ['flour', 'eggs']\n", - "num_resources = len(resources)\n", + " flour = 0\n", + " eggs = 1\n", + " resources = ['flour', 'eggs']\n", + " num_resources = len(resources)\n", "\n", - "consumption = [[0.5, 0.2], [0.4, 0.4], [0.3, 0.6]]\n", - "capacity = [20, 40]\n", - "demand = [100, 200, 300]\n", - "inside_cost = [0.6, 0.8, 0.3]\n", - "outside_cost = [0.8, 0.9, 0.4]\n", + " consumption = [[0.5, 0.2], [0.4, 0.4], [0.3, 0.6]]\n", + " capacity = [20, 40]\n", + " demand = [100, 200, 300]\n", + " inside_cost = [0.6, 0.8, 0.3]\n", + " outside_cost = [0.8, 0.9, 0.4]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "inside = [\n", - " solver.NumVar(0, 10000, 'inside[%i]' % p) for p in range(num_products)\n", - "]\n", - "outside = [\n", - " solver.NumVar(0, 10000, 'outside[%i]' % p) for p in range(num_products)\n", - "]\n", + " #\n", + " # declare variables\n", + " #\n", + " inside = [\n", + " solver.NumVar(0, 10000, 'inside[%i]' % p) for p in range(num_products)\n", + " ]\n", + " outside = [\n", + " solver.NumVar(0, 10000, 'outside[%i]' % p) for p in range(num_products)\n", + " ]\n", "\n", - "# to minimize\n", - "z = solver.Sum([\n", - " inside_cost[p] * inside[p] + outside_cost[p] * outside[p]\n", - " for p in range(num_products)\n", - "])\n", + " # to minimize\n", + " z = solver.Sum([\n", + " inside_cost[p] * inside[p] + outside_cost[p] * outside[p]\n", + " for p in range(num_products)\n", + " ])\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "for r in range(num_resources):\n", - " solver.Add(\n", - " solver.Sum([consumption[p][r] * inside[p]\n", - " for p in range(num_products)]) <= capacity[r])\n", + " #\n", + " # constraints\n", + " #\n", + " for r in range(num_resources):\n", + " solver.Add(\n", + " solver.Sum([consumption[p][r] * inside[p]\n", + " for p in range(num_products)]) <= capacity[r])\n", "\n", - "for p in range(num_products):\n", - " solver.Add(inside[p] + outside[p] >= demand[p])\n", + " for p in range(num_products):\n", + " solver.Add(inside[p] + outside[p] >= demand[p])\n", "\n", - "objective = solver.Minimize(z)\n", + " objective = solver.Minimize(z)\n", "\n", - "solver.Solve()\n", + " solver.Solve()\n", "\n", - "print()\n", - "print('z = ', solver.Objective().Value())\n", + " print()\n", + " print('z = ', solver.Objective().Value())\n", "\n", - "for p in range(num_products):\n", - " print(\n", - " products[p],\n", - " ': inside:',\n", - " inside[p].SolutionValue(),\n", - " '(ReducedCost:',\n", - " inside[p].ReducedCost(),\n", - " ')',\n", - " end=' ')\n", - " print('outside:', outside[p].SolutionValue(), ' (ReducedCost:',\n", - " outside[p].ReducedCost(), ')')\n", - "print()\n", + " for p in range(num_products):\n", + " print(\n", + " products[p],\n", + " ': inside:',\n", + " inside[p].SolutionValue(),\n", + " '(ReducedCost:',\n", + " inside[p].ReducedCost(),\n", + " ')',\n", + " end=' ')\n", + " print('outside:', outside[p].SolutionValue(), ' (ReducedCost:',\n", + " outside[p].ReducedCost(), ')')\n", + " print()\n", + "\n", + "\n", + "\n", + "sol = 'CBC'\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != 'GLPK' and sol != 'CBC':\n", + " print('Solver must be either GLPK or CBC')\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/project_scheduling_sat.ipynb b/examples/notebook/contrib/project_scheduling_sat.ipynb index 07aa0d1ac9..f3a4ecfe23 100644 --- a/examples/notebook/contrib/project_scheduling_sat.ipynb +++ b/examples/notebook/contrib/project_scheduling_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { diff --git a/examples/notebook/contrib/pyls_api.ipynb b/examples/notebook/contrib/pyls_api.ipynb index 15115862fe..49078c05a9 100644 --- a/examples/notebook/contrib/pyls_api.ipynb +++ b/examples/notebook/contrib/pyls_api.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -189,9 +189,13 @@ " print('Objective value = %d' % collector.ObjectiveValue(0))\n", "\n", "\n", - "Solve(0)\n", - "Solve(1)\n", - "Solve(2)\n", + "def main():\n", + " Solve(0)\n", + " Solve(1)\n", + " Solve(2)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/quasigroup_completion.ipynb b/examples/notebook/contrib/quasigroup_completion.ipynb index 068c2d1e94..14f1b691c5 100644 --- a/examples/notebook/contrib/quasigroup_completion.ipynb +++ b/examples/notebook/contrib/quasigroup_completion.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Quasigroup completion Google CP Solver.\n", "\n", @@ -126,8 +111,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -139,106 +132,108 @@ " [X, 4, X, X, X], [X, X, 5, X, 1]]\n", "\n", "\n", + "def main(puzzle=\"\", n=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Quasigroup completion\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Quasigroup completion\")\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "if puzzle == \"\":\n", - " puzzle = default_puzzle\n", - " n = default_n\n", + " if puzzle == \"\":\n", + " puzzle = default_puzzle\n", + " n = default_n\n", "\n", - "print(\"Problem:\")\n", - "print_game(puzzle, n, n)\n", + " print(\"Problem:\")\n", + " print_game(puzzle, n, n)\n", "\n", - "# declare variables\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", - "xflat = [x[(i, j)] for i in range(n) for j in range(n)]\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "\n", - "#\n", - "# set the clues\n", - "#\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if puzzle[i][j] > X:\n", - " solver.Add(x[i, j] == puzzle[i][j])\n", - "\n", - "#\n", - "# rows and columns must be different\n", - "#\n", - "for i in range(n):\n", - " solver.Add(solver.AllDifferent([x[i, j] for j in range(n)]))\n", - " solver.Add(solver.AllDifferent([x[j, i] for j in range(n)]))\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(xflat)\n", - "\n", - "# This version prints out the solution directly, and\n", - "# don't collect them as solver.FirstSolutionCollector(solution) do\n", - "# (db: DecisionBuilder)\n", - "db = solver.Phase(xflat, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n", - "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print(\"Solution %i\" % num_solutions)\n", - " xval = [x[(i, j)].Value() for i in range(n) for j in range(n)]\n", + " # declare variables\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(xval[i * n + j], end=\" \")\n", + " x[(i, j)] = solver.IntVar(1, n, \"x %i %i\" % (i, j))\n", + "\n", + " xflat = [x[(i, j)] for i in range(n) for j in range(n)]\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + "\n", + " #\n", + " # set the clues\n", + " #\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if puzzle[i][j] > X:\n", + " solver.Add(x[i, j] == puzzle[i][j])\n", + "\n", + " #\n", + " # rows and columns must be different\n", + " #\n", + " for i in range(n):\n", + " solver.Add(solver.AllDifferent([x[i, j] for j in range(n)]))\n", + " solver.Add(solver.AllDifferent([x[j, i] for j in range(n)]))\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(xflat)\n", + "\n", + " # This version prints out the solution directly, and\n", + " # don't collect them as solver.FirstSolutionCollector(solution) do\n", + " # (db: DecisionBuilder)\n", + " db = solver.Phase(xflat, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print(\"Solution %i\" % num_solutions)\n", + " xval = [x[(i, j)].Value() for i in range(n) for j in range(n)]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(xval[i * n + j], end=\" \")\n", + " print()\n", " print()\n", + " solver.EndSearch()\n", + "\n", + " if num_solutions == 0:\n", + " print(\"No solutions found\")\n", + "\n", + " # # Note: AllSolution may take very much RAM, hence I choose to\n", + " # # show just the first solution.\n", + " # # collector = solver.AllSolutionCollector(solution)\n", + " # collector = solver.FirstSolutionCollector(solution)\n", + " # solver.Solve(solver.Phase([x[(i,j)] for i in range(n) for j in range(n)],\n", + " # solver.CHOOSE_FIRST_UNBOUND,\n", + " # solver.ASSIGN_MIN_VALUE),\n", + " # [collector])\n", + " #\n", + " # num_solutions = collector.SolutionCount()\n", + " # print \"\\nnum_solutions: \", num_solutions\n", + " # if num_solutions > 0:\n", + " # print \"\\nJust showing the first solution...\"\n", + " # for s in range(num_solutions):\n", + " # xval = [collector.Value(s, x[(i,j)]) for i in range(n) for j in range(n)]\n", + " # for i in range(n):\n", + " # for j in range(n):\n", + " # print xval[i*n+j],\n", + " # print\n", + " # print\n", + "\n", " print()\n", - "solver.EndSearch()\n", - "\n", - "if num_solutions == 0:\n", - " print(\"No solutions found\")\n", - "\n", - "# # Note: AllSolution may take very much RAM, hence I choose to\n", - "# # show just the first solution.\n", - "# # collector = solver.AllSolutionCollector(solution)\n", - "# collector = solver.FirstSolutionCollector(solution)\n", - "# solver.Solve(solver.Phase([x[(i,j)] for i in range(n) for j in range(n)],\n", - "# solver.CHOOSE_FIRST_UNBOUND,\n", - "# solver.ASSIGN_MIN_VALUE),\n", - "# [collector])\n", - "#\n", - "# num_solutions = collector.SolutionCount()\n", - "# print \"\\nnum_solutions: \", num_solutions\n", - "# if num_solutions > 0:\n", - "# print \"\\nJust showing the first solution...\"\n", - "# for s in range(num_solutions):\n", - "# xval = [collector.Value(s, x[(i,j)]) for i in range(n) for j in range(n)]\n", - "# for i in range(n):\n", - "# for j in range(n):\n", - "# print xval[i*n+j],\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", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", "\n", "\n", "#\n", "# Read a problem instance from a file\n", - "#def read_problem(file):\n", + "#\n", + "def read_problem(file):\n", " f = open(file, \"r\")\n", " n = int(f.readline())\n", " game = []\n", @@ -269,6 +264,15 @@ " print(\"% 2s\" % game[i][j], end=\" \")\n", " print(\"\")\n", "\n", + "\n", + "\n", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " print(\"Problem instance from\", file)\n", + " [game, n] = read_problem(file)\n", + " main(game, n)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/regular.ipynb b/examples/notebook/contrib/regular.ipynb index f0e4bbf406..91243b3905 100644 --- a/examples/notebook/contrib/regular.ipynb +++ b/examples/notebook/contrib/regular.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Global constraint regular in Google CP Solver.\n", "\n", @@ -111,8 +96,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", @@ -241,57 +234,61 @@ " return t_matrix\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Regular test')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "this_len = 10\n", - "pp = [3, 2, 1]\n", + " this_len = 10\n", + " pp = [3, 2, 1]\n", "\n", - "transition_fn = make_transition_matrix(pp)\n", - "n_states = len(transition_fn)\n", - "input_max = 2\n", + " transition_fn = make_transition_matrix(pp)\n", + " n_states = len(transition_fn)\n", + " input_max = 2\n", "\n", - "# Note: we use '1' and '2' (rather than 0 and 1)\n", - "# since 0 represents the failing state.\n", - "initial_state = 1\n", + " # Note: we use '1' and '2' (rather than 0 and 1)\n", + " # since 0 represents the failing state.\n", + " initial_state = 1\n", "\n", - "accepting_states = [n_states]\n", + " accepting_states = [n_states]\n", "\n", - "# declare variables\n", - "reg_input = [\n", - " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", - "]\n", + " # declare variables\n", + " reg_input = [\n", + " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", + " ]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "regular(reg_input, n_states, input_max, transition_fn, initial_state,\n", - " accepting_states)\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_MIN_SIZE_HIGHEST_MAX,\n", - " solver.ASSIGN_MIN_VALUE)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(reg_input, solver.CHOOSE_MIN_SIZE_HIGHEST_MAX,\n", + " solver.ASSIGN_MIN_VALUE)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", - " num_solutions += 1\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", + " num_solutions += 1\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/regular_table.ipynb b/examples/notebook/contrib/regular_table.ipynb index 5587988ae7..932713e7c4 100644 --- a/examples/notebook/contrib/regular_table.ipynb +++ b/examples/notebook/contrib/regular_table.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Global constraint regular in Google CP Solver.\n", "\n", @@ -111,8 +96,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", @@ -234,57 +227,61 @@ " return t_matrix\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Regular test')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "this_len = 10\n", - "pp = [3, 2, 1]\n", + " this_len = 10\n", + " pp = [3, 2, 1]\n", "\n", - "transition_fn = make_transition_matrix(pp)\n", - "n_states = len(transition_fn)\n", - "input_max = 2\n", + " transition_fn = make_transition_matrix(pp)\n", + " n_states = len(transition_fn)\n", + " input_max = 2\n", "\n", - "# Note: we use '1' and '2' (rather than 0 and 1)\n", - "# since 0 represents the failing state.\n", - "initial_state = 1\n", + " # Note: we use '1' and '2' (rather than 0 and 1)\n", + " # since 0 represents the failing state.\n", + " initial_state = 1\n", "\n", - "accepting_states = [n_states]\n", + " accepting_states = [n_states]\n", "\n", - "# declare variables\n", - "reg_input = [\n", - " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", - "]\n", + " # declare variables\n", + " reg_input = [\n", + " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", + " ]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "regular(reg_input, n_states, input_max, transition_fn, initial_state,\n", - " accepting_states)\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_MIN_SIZE_HIGHEST_MAX,\n", - " solver.ASSIGN_MIN_VALUE)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(reg_input, solver.CHOOSE_MIN_SIZE_HIGHEST_MAX,\n", + " solver.ASSIGN_MIN_VALUE)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", - " num_solutions += 1\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", + " num_solutions += 1\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/regular_table2.ipynb b/examples/notebook/contrib/regular_table2.ipynb index cc2da813c3..109e4c5a7b 100644 --- a/examples/notebook/contrib/regular_table2.ipynb +++ b/examples/notebook/contrib/regular_table2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Global constraint regular in Google CP Solver.\n", "\n", @@ -111,8 +96,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", @@ -218,57 +211,61 @@ " return t_matrix\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Regular test')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Regular test')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "this_len = 10\n", - "pp = [3, 2, 1]\n", + " this_len = 10\n", + " pp = [3, 2, 1]\n", "\n", - "transition_fn = make_transition_matrix(pp)\n", - "n_states = len(transition_fn)\n", - "input_max = 2\n", + " transition_fn = make_transition_matrix(pp)\n", + " n_states = len(transition_fn)\n", + " input_max = 2\n", "\n", - "# Note: we use '1' and '2' (rather than 0 and 1)\n", - "# since 0 represents the failing state.\n", - "initial_state = 1\n", + " # Note: we use '1' and '2' (rather than 0 and 1)\n", + " # since 0 represents the failing state.\n", + " initial_state = 1\n", "\n", - "accepting_states = [n_states]\n", + " accepting_states = [n_states]\n", "\n", - "# declare variables\n", - "reg_input = [\n", - " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", - "]\n", + " # declare variables\n", + " reg_input = [\n", + " solver.IntVar(1, input_max, 'reg_input[%i]' % i) for i in range(this_len)\n", + " ]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "regular(reg_input, n_states, input_max, transition_fn, initial_state,\n", - " accepting_states)\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_MIN_SIZE_HIGHEST_MAX,\n", - " solver.ASSIGN_MIN_VALUE)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(reg_input, solver.CHOOSE_MIN_SIZE_HIGHEST_MAX,\n", + " solver.ASSIGN_MIN_VALUE)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", - " num_solutions += 1\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print('reg_input:', [reg_input[i].Value() - 1 for i in range(this_len)])\n", + " num_solutions += 1\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/rogo2.ipynb b/examples/notebook/contrib/rogo2.ipynb index 48b340ea82..06ae6e8ff9 100644 --- a/examples/notebook/contrib/rogo2.ipynb +++ b/examples/notebook/contrib/rogo2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Rogo puzzle solver in Google CP Solver.\n", "\n", @@ -118,128 +103,137 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "import re\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(problem, rows, cols, max_steps):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Rogo grid puzzle\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Rogo grid puzzle\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "W = 0\n", - "B = -1\n", - "print(\"rows: %i cols: %i max_steps: %i\" % (rows, cols, max_steps))\n", + " #\n", + " # data\n", + " #\n", + " W = 0\n", + " B = -1\n", + " print(\"rows: %i cols: %i max_steps: %i\" % (rows, cols, max_steps))\n", "\n", - "problem_flatten = [problem[i][j] for i in range(rows) for j in range(cols)]\n", - "max_point = max(problem_flatten)\n", - "print(\"max_point:\", max_point)\n", - "max_sum = sum(problem_flatten)\n", - "print(\"max_sum:\", max_sum)\n", - "print()\n", - "\n", - "#\n", - "# declare variables\n", - "#\n", - "\n", - "# the coordinates\n", - "x = [solver.IntVar(0, rows - 1, \"x[%i]\" % i) for i in range(max_steps)]\n", - "y = [solver.IntVar(0, cols - 1, \"y[%i]\" % i) for i in range(max_steps)]\n", - "\n", - "# the collected points\n", - "points = [\n", - " solver.IntVar(0, max_point, \"points[%i]\" % i) for i in range(max_steps)\n", - "]\n", - "\n", - "# objective: sum of points in the path\n", - "sum_points = solver.IntVar(0, max_sum)\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "\n", - "# all coordinates must be unique\n", - "for s in range(max_steps):\n", - " for t in range(s + 1, max_steps):\n", - " b1 = x[s] != x[t]\n", - " b2 = y[s] != y[t]\n", - " solver.Add(b1 + b2 >= 1)\n", - "\n", - "# calculate the points (to maximize)\n", - "for s in range(max_steps):\n", - " solver.Add(points[s] == solver.Element(problem_flatten, x[s] * cols + y[s]))\n", - "\n", - "solver.Add(sum_points == sum(points))\n", - "\n", - "# ensure that there are not black cells in\n", - "# the path\n", - "for s in range(max_steps):\n", - " solver.Add(solver.Element(problem_flatten, x[s] * cols + y[s]) != B)\n", - "\n", - "# get the path\n", - "for s in range(max_steps - 1):\n", - " solver.Add(abs(x[s] - x[s + 1]) + abs(y[s] - y[s + 1]) == 1)\n", - "\n", - "# close the path around the corner\n", - "solver.Add(abs(x[max_steps - 1] - x[0]) + abs(y[max_steps - 1] - y[0]) == 1)\n", - "\n", - "# symmetry breaking: the cell with lowest coordinates\n", - "# should be in the first step.\n", - "for i in range(1, max_steps):\n", - " solver.Add(x[0] * cols + y[0] < x[i] * cols + y[i])\n", - "\n", - "# symmetry breaking: second step is larger than\n", - "# first step\n", - "# solver.Add(x[0]*cols+y[0] < x[1]*cols+y[1])\n", - "\n", - "#\n", - "# objective\n", - "#\n", - "objective = solver.Maximize(sum_points, 1)\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "# db = solver.Phase(x + y,\n", - "# solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n", - "# solver.ASSIGN_MIN_VALUE)\n", - "\n", - "# Default search\n", - "parameters = pywrapcp.DefaultPhaseParameters()\n", - "\n", - "parameters.heuristic_period = 200000\n", - "# parameters.var_selection_schema = parameters.CHOOSE_MAX_SUM_IMPACT\n", - "parameters.var_selection_schema = parameters.CHOOSE_MAX_AVERAGE_IMPACT # <-\n", - "# parameters.var_selection_schema = parameters.CHOOSE_MAX_VALUE_IMPACT\n", - "\n", - "parameters.value_selection_schema = parameters.SELECT_MIN_IMPACT # <-\n", - "# parameters.value_selection_schema = parameters.SELECT_MAX_IMPACT\n", - "\n", - "# parameters.initialization_splits = 10\n", - "\n", - "db = solver.DefaultPhase(x + y, parameters)\n", - "\n", - "solver.NewSearch(db, [objective])\n", - "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print(\"sum_points:\", sum_points.Value())\n", - " print(\"adding 1 to coords...\")\n", - " for s in range(max_steps):\n", - " print(\"%i %i\" % (x[s].Value() + 1, y[s].Value() + 1))\n", + " problem_flatten = [problem[i][j] for i in range(rows) for j in range(cols)]\n", + " max_point = max(problem_flatten)\n", + " print(\"max_point:\", max_point)\n", + " max_sum = sum(problem_flatten)\n", + " print(\"max_sum:\", max_sum)\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", + " # declare variables\n", + " #\n", + "\n", + " # the coordinates\n", + " x = [solver.IntVar(0, rows - 1, \"x[%i]\" % i) for i in range(max_steps)]\n", + " y = [solver.IntVar(0, cols - 1, \"y[%i]\" % i) for i in range(max_steps)]\n", + "\n", + " # the collected points\n", + " points = [\n", + " solver.IntVar(0, max_point, \"points[%i]\" % i) for i in range(max_steps)\n", + " ]\n", + "\n", + " # objective: sum of points in the path\n", + " sum_points = solver.IntVar(0, max_sum)\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + "\n", + " # all coordinates must be unique\n", + " for s in range(max_steps):\n", + " for t in range(s + 1, max_steps):\n", + " b1 = x[s] != x[t]\n", + " b2 = y[s] != y[t]\n", + " solver.Add(b1 + b2 >= 1)\n", + "\n", + " # calculate the points (to maximize)\n", + " for s in range(max_steps):\n", + " solver.Add(points[s] == solver.Element(problem_flatten, x[s] * cols + y[s]))\n", + "\n", + " solver.Add(sum_points == sum(points))\n", + "\n", + " # ensure that there are not black cells in\n", + " # the path\n", + " for s in range(max_steps):\n", + " solver.Add(solver.Element(problem_flatten, x[s] * cols + y[s]) != B)\n", + "\n", + " # get the path\n", + " for s in range(max_steps - 1):\n", + " solver.Add(abs(x[s] - x[s + 1]) + abs(y[s] - y[s + 1]) == 1)\n", + "\n", + " # close the path around the corner\n", + " solver.Add(abs(x[max_steps - 1] - x[0]) + abs(y[max_steps - 1] - y[0]) == 1)\n", + "\n", + " # symmetry breaking: the cell with lowest coordinates\n", + " # should be in the first step.\n", + " for i in range(1, max_steps):\n", + " solver.Add(x[0] * cols + y[0] < x[i] * cols + y[i])\n", + "\n", + " # symmetry breaking: second step is larger than\n", + " # first step\n", + " # solver.Add(x[0]*cols+y[0] < x[1]*cols+y[1])\n", + "\n", + " #\n", + " # objective\n", + " #\n", + " objective = solver.Maximize(sum_points, 1)\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " # db = solver.Phase(x + y,\n", + " # solver.CHOOSE_MIN_SIZE_LOWEST_MIN,\n", + " # solver.ASSIGN_MIN_VALUE)\n", + "\n", + " # Default search\n", + " parameters = pywrapcp.DefaultPhaseParameters()\n", + "\n", + " parameters.heuristic_period = 200000\n", + " # parameters.var_selection_schema = parameters.CHOOSE_MAX_SUM_IMPACT\n", + " parameters.var_selection_schema = parameters.CHOOSE_MAX_AVERAGE_IMPACT # <-\n", + " # parameters.var_selection_schema = parameters.CHOOSE_MAX_VALUE_IMPACT\n", + "\n", + " parameters.value_selection_schema = parameters.SELECT_MIN_IMPACT # <-\n", + " # parameters.value_selection_schema = parameters.SELECT_MAX_IMPACT\n", + "\n", + " # parameters.initialization_splits = 10\n", + "\n", + " db = solver.DefaultPhase(x + y, parameters)\n", + "\n", + " solver.NewSearch(db, [objective])\n", + "\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print(\"sum_points:\", sum_points.Value())\n", + " print(\"adding 1 to coords...\")\n", + " for s in range(max_steps):\n", + " print(\"%i %i\" % (x[s].Value() + 1, y[s].Value() + 1))\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", "\n", "# Default problem:\n", @@ -249,14 +243,19 @@ "#\n", "# This has 48 solutions with symmetries;\n", "# 4 when the path symmetry is removed.\n", - "#rows = 5\n", + "#\n", + "rows = 5\n", "cols = 9\n", "max_steps = 12\n", "W = 0\n", "B = -1\n", "problem = [[2, W, W, W, W, W, W, W, W], [W, 3, W, W, 1, W, W, 2, W],\n", " [W, W, W, W, W, W, B, W, 2], [W, W, 2, B, W, W, W, W, W],\n", - " [W, W, W, W, 2, W, W, 1, W]]\n" + " [W, W, W, W, 2, W, W, 1, W]]\n", + "if len(sys.argv) > 1:\n", + " exec(compile(open(sys.argv[1]).read(), sys.argv[1], \"exec\"))\n", + "main(problem, rows, cols, max_steps)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/rostering_with_travel.ipynb b/examples/notebook/contrib/rostering_with_travel.ipynb index a98c49d56e..aaa4f9a316 100644 --- a/examples/notebook/contrib/rostering_with_travel.ipynb +++ b/examples/notebook/contrib/rostering_with_travel.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -184,7 +184,11 @@ " print(' - wall time : %f ms' % solver.WallTime())\n", "\n", "\n", - "SolveRosteringWithTravel()\n", + "def main():\n", + " SolveRosteringWithTravel()\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/safe_cracking.ipynb b/examples/notebook/contrib/safe_cracking.ipynb index 75efc03096..7118dce680 100644 --- a/examples/notebook/contrib/safe_cracking.ipynb +++ b/examples/notebook/contrib/safe_cracking.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Safe cracking puzzle in Google CP Solver.\n", "\n", @@ -118,60 +103,72 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Safe cracking puzzle')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Safe cracking puzzle')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 9\n", - "digits = list(range(1, n + 1))\n", + " #\n", + " # data\n", + " #\n", + " n = 9\n", + " digits = list(range(1, n + 1))\n", "\n", - "#\n", - "# variables\n", - "#\n", + " #\n", + " # variables\n", + " #\n", "\n", - "LD = [solver.IntVar(digits, 'LD[%i]' % i) for i in range(n)]\n", - "C1, C2, C3, C4, C5, C6, C7, C8, C9 = LD\n", + " LD = [solver.IntVar(digits, 'LD[%i]' % i) for i in range(n)]\n", + " C1, C2, C3, C4, C5, C6, C7, C8, C9 = LD\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(LD))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(LD))\n", "\n", - "solver.Add(C4 - C6 == C7)\n", - "solver.Add(C1 * C2 * C3 == C8 + C9)\n", - "solver.Add(C2 + C3 + C6 < C8)\n", - "solver.Add(C9 < C8)\n", - "for i in range(n):\n", - " solver.Add(LD[i] != i + 1)\n", + " solver.Add(C4 - C6 == C7)\n", + " solver.Add(C1 * C2 * C3 == C8 + C9)\n", + " solver.Add(C2 + C3 + C6 < C8)\n", + " solver.Add(C9 < C8)\n", + " for i in range(n):\n", + " solver.Add(LD[i] != i + 1)\n", "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(LD, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(LD, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", + " num_solutions = 0\n", "\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('LD:', [LD[i].Value() for i in range(n)])\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('LD:', [LD[i].Value() for i in range(n)])\n", "\n", - "solver.EndSearch()\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/scheduling_speakers.ipynb b/examples/notebook/contrib/scheduling_speakers.ipynb index ffb8ed0151..5aeb02d36c 100644 --- a/examples/notebook/contrib/scheduling_speakers.ipynb +++ b/examples/notebook/contrib/scheduling_speakers.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Scheduling speakers problem in Google CP Solver.\n", "\n", @@ -102,64 +87,76 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Scheduling speakers')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Scheduling speakers')\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 6 # number of speakers\n", + " #\n", + " # data\n", + " #\n", + " n = 6 # number of speakers\n", "\n", - "# slots available to speak\n", - "available = [\n", - " # Reasoning:\n", - " [3, 4, 5, 6], # 2) the only one with 6 after speaker F -> 1\n", - " [3, 4], # 5) 3 or 4\n", - " [2, 3, 4, 5], # 3) only with 5 after F -> 1 and A -> 6\n", - " [2, 3, 4], # 4) only with 2 after C -> 5 and F -> 1\n", - " [3, 4], # 5) 3 or 4\n", - " [1, 2, 3, 4, 5, 6] # 1) the only with 1\n", - "]\n", + " # slots available to speak\n", + " available = [\n", + " # Reasoning:\n", + " [3, 4, 5, 6], # 2) the only one with 6 after speaker F -> 1\n", + " [3, 4], # 5) 3 or 4\n", + " [2, 3, 4, 5], # 3) only with 5 after F -> 1 and A -> 6\n", + " [2, 3, 4], # 4) only with 2 after C -> 5 and F -> 1\n", + " [3, 4], # 5) 3 or 4\n", + " [1, 2, 3, 4, 5, 6] # 1) the only with 1\n", + " ]\n", "\n", - "#\n", - "# variables\n", - "#\n", - "x = [solver.IntVar(1, n, 'x[%i]' % i) for i in range(n)]\n", + " #\n", + " # variables\n", + " #\n", + " x = [solver.IntVar(1, n, 'x[%i]' % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", "\n", - "for i in range(n):\n", - " solver.Add(solver.MemberCt(x[i], available[i]))\n", + " for i in range(n):\n", + " solver.Add(solver.MemberCt(x[i], available[i]))\n", "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db)\n", + " solver.NewSearch(db)\n", "\n", - "num_solutions = 0\n", + " num_solutions = 0\n", "\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('x:', [x[i].Value() for i in range(n)])\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('x:', [x[i].Value() for i in range(n)])\n", "\n", - "solver.EndSearch()\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/scheduling_with_transitions_sat.ipynb b/examples/notebook/contrib/scheduling_with_transitions_sat.ipynb index 5e15e27b94..bf56218df9 100644 --- a/examples/notebook/contrib/scheduling_with_transitions_sat.ipynb +++ b/examples/notebook/contrib/scheduling_with_transitions_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,18 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Scheduling problem with transition time between tasks and transitions costs.\n", + "\n", + "@author: CSLiu2\n", + "\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,13 +86,6 @@ "metadata": {}, "outputs": [], "source": [ - "# -*- coding: utf-8 -*-\n", - "\"\"\"Scheduling problem with transition time between tasks and transitions costs.\n", - "\n", - "@author: CSLiu2\n", - "\"\"\"\n", - "\n", - "\n", "import argparse\n", "import collections\n", "\n", @@ -116,292 +121,296 @@ " self.__solution_count += 1\n", "\n", "\n", - "\"\"\"Solves the scheduling with transitions problem.\"\"\"\n", + "def main(args):\n", + " \"\"\"Solves the scheduling with transitions problem.\"\"\"\n", "\n", - "instance = args.problem_instance\n", - "parameters = args.params\n", - "output_proto = args.output_proto\n", + " instance = args.problem_instance\n", + " parameters = args.params\n", + " output_proto = args.output_proto\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Data.\n", - "small_jobs = [[[(100, 0, 'R6'), (2, 1, 'R6')]],\n", - " [[(2, 0, 'R3'), (100, 1, 'R3')]],\n", - " [[(100, 0, 'R1'), (16, 1, 'R1')]],\n", - " [[(1, 0, 'R1'), (38, 1, 'R1')]], [[(14, 0, 'R1'), (10, 1,\n", - " 'R1')]],\n", - " [[(16, 0, 'R3'), (17, 1, 'R3')]],\n", - " [[(14, 0, 'R3'), (14, 1, 'R3')]],\n", - " [[(14, 0, 'R3'), (15, 1, 'R3')]],\n", - " [[(14, 0, 'R3'), (13, 1, 'R3')]],\n", - " [[(100, 0, 'R1'), (38, 1, 'R1')]]]\n", + " #----------------------------------------------------------------------------\n", + " # Data.\n", + " small_jobs = [[[(100, 0, 'R6'), (2, 1, 'R6')]],\n", + " [[(2, 0, 'R3'), (100, 1, 'R3')]],\n", + " [[(100, 0, 'R1'), (16, 1, 'R1')]],\n", + " [[(1, 0, 'R1'), (38, 1, 'R1')]], [[(14, 0, 'R1'), (10, 1,\n", + " 'R1')]],\n", + " [[(16, 0, 'R3'), (17, 1, 'R3')]],\n", + " [[(14, 0, 'R3'), (14, 1, 'R3')]],\n", + " [[(14, 0, 'R3'), (15, 1, 'R3')]],\n", + " [[(14, 0, 'R3'), (13, 1, 'R3')]],\n", + " [[(100, 0, 'R1'), (38, 1, 'R1')]]]\n", "\n", - "large_jobs = [\n", - " [[(-1, 0, 'R1'), (10, 1, 'R1')]], [[(9, 0, 'R3'),\n", - " (22, 1, 'R3')]],\n", - " [[(-1, 0, 'R3'), (13, 1, 'R3')]], [[(-1, 0, 'R3'), (38, 1, 'R3')]],\n", - " [[(-1, 0, 'R3'), (38, 1, 'R3')]], [[(-1, 0, 'R3'), (16, 1, 'R3')]],\n", - " [[(-1, 0, 'R3'), (11, 1, 'R3')]], [[(-1, 0, 'R3'), (13, 1, 'R3')]],\n", - " [[(13, 0, 'R3'), (-1, 1, 'R3')]], [[(13, 0, 'R3'), (-1, 1, 'R3')]],\n", - " [[(-1, 0, 'R3'), (15, 1, 'R3')]], [[(12, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(14, 0, 'R1'), (-1, 1, 'R1')]], [[(13, 0, 'R3'), (-1, 1, 'R3')]],\n", - " [[(-1, 0, 'R3'), (15, 1, 'R3')]], [[(14, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(13, 0, 'R3'), (-1, 1, 'R3')]], [[(14, 0, 'R3'), (-1, 1, 'R3')]],\n", - " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(15, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(-1, 0, 'R2'), (16, 1, 'R2')]], [[(-1, 0, 'R2'), (16, 1, 'R2')]],\n", - " [[(-1, 0, 'R5'), (27, 1, 'R5')]], [[(-1, 0, 'R5'), (13, 1, 'R5')]],\n", - " [[(-1, 0, 'R5'), (13, 1, 'R5')]], [[(-1, 0, 'R5'), (13, 1, 'R5')]],\n", - " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(-1, 0, 'R1'), (17, 1, 'R1')]],\n", - " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(16, 0, 'R4'), (-1, 1, 'R4')]], [[(16, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(16, 0, 'R4'), (-1, 1, 'R4')]], [[(16, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(12, 0, 'R1'), (-1, 1, 'R1')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(-1, 0, 'R5'), (14, 1, 'R5')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", - " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", - " [[(13, 0, 'R6'), (-1, 1, 'R6')]], [[(13, 0, 'R2'), (-1, 1, 'R2')]],\n", - " [[(-1, 0, 'R6'), (12, 1, 'R6')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", - " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(-1, 0, 'R6'), (14, 1, 'R6')]],\n", - " [[(-1, 0, 'R5'), (5, 1, 'R5')]], [[(3, 0, 'R2'), (-1, 1, 'R2')]],\n", - " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", - " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R5'), (1, 1, 'R5')]],\n", - " [[(1, 0, 'R2'), (-1, 1, 'R2')]], [[(-1, 0, 'R2'), (19, 1, 'R2')]],\n", - " [[(13, 0, 'R4'), (-1, 1, 'R4')]], [[(12, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(-1, 0, 'R3'), (2, 1, 'R3')]], [[(11, 0, 'R4'), (-1, 1, 'R4')]],\n", - " [[(6, 0, 'R6'), (-1, 1, 'R6')]], [[(6, 0, 'R6'), (-1, 1, 'R6')]],\n", - " [[(1, 0, 'R2'), (-1, 1, 'R2')]], [[(12, 0, 'R4'), (-1, 1, 'R4')]]\n", - "]\n", + " large_jobs = [\n", + " [[(-1, 0, 'R1'), (10, 1, 'R1')]], [[(9, 0, 'R3'),\n", + " (22, 1, 'R3')]],\n", + " [[(-1, 0, 'R3'), (13, 1, 'R3')]], [[(-1, 0, 'R3'), (38, 1, 'R3')]],\n", + " [[(-1, 0, 'R3'), (38, 1, 'R3')]], [[(-1, 0, 'R3'), (16, 1, 'R3')]],\n", + " [[(-1, 0, 'R3'), (11, 1, 'R3')]], [[(-1, 0, 'R3'), (13, 1, 'R3')]],\n", + " [[(13, 0, 'R3'), (-1, 1, 'R3')]], [[(13, 0, 'R3'), (-1, 1, 'R3')]],\n", + " [[(-1, 0, 'R3'), (15, 1, 'R3')]], [[(12, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(14, 0, 'R1'), (-1, 1, 'R1')]], [[(13, 0, 'R3'), (-1, 1, 'R3')]],\n", + " [[(-1, 0, 'R3'), (15, 1, 'R3')]], [[(14, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(13, 0, 'R3'), (-1, 1, 'R3')]], [[(14, 0, 'R3'), (-1, 1, 'R3')]],\n", + " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(15, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(-1, 0, 'R2'), (16, 1, 'R2')]], [[(-1, 0, 'R2'), (16, 1, 'R2')]],\n", + " [[(-1, 0, 'R5'), (27, 1, 'R5')]], [[(-1, 0, 'R5'), (13, 1, 'R5')]],\n", + " [[(-1, 0, 'R5'), (13, 1, 'R5')]], [[(-1, 0, 'R5'), (13, 1, 'R5')]],\n", + " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(-1, 0, 'R1'), (17, 1, 'R1')]],\n", + " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(16, 0, 'R4'), (-1, 1, 'R4')]], [[(16, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(16, 0, 'R4'), (-1, 1, 'R4')]], [[(16, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(12, 0, 'R1'), (-1, 1, 'R1')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(-1, 0, 'R5'), (14, 1, 'R5')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(14, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(14, 0, 'R4'), (-1, 1, 'R4')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", + " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", + " [[(13, 0, 'R6'), (-1, 1, 'R6')]], [[(13, 0, 'R2'), (-1, 1, 'R2')]],\n", + " [[(-1, 0, 'R6'), (12, 1, 'R6')]], [[(13, 0, 'R1'), (-1, 1, 'R1')]],\n", + " [[(13, 0, 'R1'), (-1, 1, 'R1')]], [[(-1, 0, 'R6'), (14, 1, 'R6')]],\n", + " [[(-1, 0, 'R5'), (5, 1, 'R5')]], [[(3, 0, 'R2'), (-1, 1, 'R2')]],\n", + " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R1'), (21, 1, 'R1')]],\n", + " [[(-1, 0, 'R1'), (21, 1, 'R1')]], [[(-1, 0, 'R5'), (1, 1, 'R5')]],\n", + " [[(1, 0, 'R2'), (-1, 1, 'R2')]], [[(-1, 0, 'R2'), (19, 1, 'R2')]],\n", + " [[(13, 0, 'R4'), (-1, 1, 'R4')]], [[(12, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(-1, 0, 'R3'), (2, 1, 'R3')]], [[(11, 0, 'R4'), (-1, 1, 'R4')]],\n", + " [[(6, 0, 'R6'), (-1, 1, 'R6')]], [[(6, 0, 'R6'), (-1, 1, 'R6')]],\n", + " [[(1, 0, 'R2'), (-1, 1, 'R2')]], [[(12, 0, 'R4'), (-1, 1, 'R4')]]\n", + " ]\n", "\n", - "jobs = small_jobs if instance == 0 else large_jobs\n", + " jobs = small_jobs if instance == 0 else large_jobs\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Helper data.\n", - "num_jobs = len(jobs)\n", - "all_jobs = range(num_jobs)\n", - "num_machines = 2\n", - "all_machines = range(num_machines)\n", + " #----------------------------------------------------------------------------\n", + " # Helper data.\n", + " num_jobs = len(jobs)\n", + " all_jobs = range(num_jobs)\n", + " num_machines = 2\n", + " all_machines = range(num_machines)\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Model.\n", - "model = cp_model.CpModel()\n", + " #----------------------------------------------------------------------------\n", + " # Model.\n", + " model = cp_model.CpModel()\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Compute a maximum makespan greedily.\n", - "horizon = 0\n", - "for job in jobs:\n", - " for task in job:\n", - " max_task_duration = 0\n", - " for alternative in task:\n", - " max_task_duration = max(max_task_duration, alternative[0])\n", - " horizon += max_task_duration\n", + " #----------------------------------------------------------------------------\n", + " # Compute a maximum makespan greedily.\n", + " horizon = 0\n", + " for job in jobs:\n", + " for task in job:\n", + " max_task_duration = 0\n", + " for alternative in task:\n", + " max_task_duration = max(max_task_duration, alternative[0])\n", + " horizon += max_task_duration\n", "\n", - "print('Horizon = %i' % horizon)\n", + " print('Horizon = %i' % horizon)\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Global storage of variables.\n", - "intervals_per_machines = collections.defaultdict(list)\n", - "presences_per_machines = collections.defaultdict(list)\n", - "starts_per_machines = collections.defaultdict(list)\n", - "ends_per_machines = collections.defaultdict(list)\n", - "resources_per_machines = collections.defaultdict(list)\n", - "ranks_per_machines = collections.defaultdict(list)\n", + " #----------------------------------------------------------------------------\n", + " # Global storage of variables.\n", + " intervals_per_machines = collections.defaultdict(list)\n", + " presences_per_machines = collections.defaultdict(list)\n", + " starts_per_machines = collections.defaultdict(list)\n", + " ends_per_machines = collections.defaultdict(list)\n", + " resources_per_machines = collections.defaultdict(list)\n", + " ranks_per_machines = collections.defaultdict(list)\n", "\n", - "job_starts = {} # indexed by (job_id, task_id).\n", - "job_presences = {} # indexed by (job_id, task_id, alt_id).\n", - "job_ranks = {} # indexed by (job_id, task_id, alt_id).\n", - "job_ends = [] # indexed by job_id\n", + " job_starts = {} # indexed by (job_id, task_id).\n", + " job_presences = {} # indexed by (job_id, task_id, alt_id).\n", + " job_ranks = {} # indexed by (job_id, task_id, alt_id).\n", + " job_ends = [] # indexed by job_id\n", "\n", - "#----------------------------------------------------------------------------\n", - "# Scan the jobs and create the relevant variables and intervals.\n", - "for job_id in all_jobs:\n", - " job = jobs[job_id]\n", - " num_tasks = len(job)\n", - " previous_end = None\n", - " for task_id in range(num_tasks):\n", - " task = job[task_id]\n", - "\n", - " min_duration = task[0][0]\n", - " max_duration = task[0][0]\n", - "\n", - " num_alternatives = len(task)\n", - " all_alternatives = range(num_alternatives)\n", - "\n", - " for alt_id in range(1, num_alternatives):\n", - " alt_duration = task[alt_id][0]\n", - " min_duration = min(min_duration, alt_duration)\n", - " max_duration = max(max_duration, alt_duration)\n", - "\n", - " # Create main interval for the task.\n", - " suffix_name = '_j%i_t%i' % (job_id, task_id)\n", - " start = model.NewIntVar(0, horizon, 'start' + suffix_name)\n", - " duration = model.NewIntVar(min_duration, max_duration,\n", - " 'duration' + suffix_name)\n", - " end = model.NewIntVar(0, horizon, 'end' + suffix_name)\n", - "\n", - " # Store the start for the solution.\n", - " job_starts[(job_id, task_id)] = start\n", - "\n", - " # Add precedence with previous task in the same job.\n", - " if previous_end:\n", - " model.Add(start >= previous_end)\n", - " previous_end = end\n", - "\n", - " # Create alternative intervals.\n", - " l_presences = []\n", - " for alt_id in all_alternatives:\n", - " ### add to link interval with eqp constraint.\n", - " ### process time = -1 cannot be processed at this machine.\n", - " if jobs[job_id][task_id][alt_id][0] == -1:\n", - " continue\n", - " alt_suffix = '_j%i_t%i_a%i' % (job_id, task_id, alt_id)\n", - " l_presence = model.NewBoolVar('presence' + alt_suffix)\n", - " l_start = model.NewIntVar(0, horizon, 'start' + alt_suffix)\n", - " l_duration = task[alt_id][0]\n", - " l_end = model.NewIntVar(0, horizon, 'end' + alt_suffix)\n", - " l_interval = model.NewOptionalIntervalVar(\n", - " l_start, l_duration, l_end, l_presence, 'interval' + alt_suffix)\n", - " l_rank = model.NewIntVar(-1, num_jobs, 'rank' + alt_suffix)\n", - " l_presences.append(l_presence)\n", - " l_machine = task[alt_id][1]\n", - " l_type = task[alt_id][2]\n", - "\n", - " # Link the master variables with the local ones.\n", - " model.Add(start == l_start).OnlyEnforceIf(l_presence)\n", - " model.Add(duration == l_duration).OnlyEnforceIf(l_presence)\n", - " model.Add(end == l_end).OnlyEnforceIf(l_presence)\n", - "\n", - " # Add the local variables to the right machine.\n", - " intervals_per_machines[l_machine].append(l_interval)\n", - " starts_per_machines[l_machine].append(l_start)\n", - " ends_per_machines[l_machine].append(l_end)\n", - " presences_per_machines[l_machine].append(l_presence)\n", - " resources_per_machines[l_machine].append(l_type)\n", - " ranks_per_machines[l_machine].append(l_rank)\n", - "\n", - " # Store the variables for the solution.\n", - " job_presences[(job_id, task_id, alt_id)] = l_presence\n", - " job_ranks[(job_id, task_id, alt_id)] = l_rank\n", - "\n", - " # Only one machine can process each lot.\n", - " model.Add(sum(l_presences) == 1)\n", - "\n", - " job_ends.append(previous_end)\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Create machines constraints nonoverlap process\n", - "for machine_id in all_machines:\n", - " intervals = intervals_per_machines[machine_id]\n", - " if len(intervals) > 1:\n", - " model.AddNoOverlap(intervals)\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Transition times and transition costs using a circuit constraint.\n", - "switch_literals = []\n", - "for machine_id in all_machines:\n", - " machine_starts = starts_per_machines[machine_id]\n", - " machine_ends = ends_per_machines[machine_id]\n", - " machine_presences = presences_per_machines[machine_id]\n", - " machine_resources = resources_per_machines[machine_id]\n", - " machine_ranks = ranks_per_machines[machine_id]\n", - " intervals = intervals_per_machines[machine_id]\n", - " arcs = []\n", - " num_machine_tasks = len(machine_starts)\n", - " all_machine_tasks = range(num_machine_tasks)\n", - "\n", - " for i in all_machine_tasks:\n", - " # Initial arc from the dummy node (0) to a task.\n", - " start_lit = model.NewBoolVar('')\n", - " arcs.append([0, i + 1, start_lit])\n", - " # If this task is the first, set both rank and start to 0.\n", - " model.Add(machine_ranks[i] == 0).OnlyEnforceIf(start_lit)\n", - " model.Add(machine_starts[i] == 0).OnlyEnforceIf(start_lit)\n", - " # Final arc from an arc to the dummy node.\n", - " arcs.append([i + 1, 0, model.NewBoolVar('')])\n", - " # Self arc if the task is not performed.\n", - " arcs.append([i + 1, i + 1, machine_presences[i].Not()])\n", - " model.Add(machine_ranks[i] == -1).OnlyEnforceIf(\n", - " machine_presences[i].Not())\n", - "\n", - " for j in all_machine_tasks:\n", - " if i == j:\n", - " continue\n", - "\n", - " lit = model.NewBoolVar('%i follows %i' % (j, i))\n", - " arcs.append([i + 1, j + 1, lit])\n", - " model.AddImplication(lit, machine_presences[i])\n", - " model.AddImplication(lit, machine_presences[j])\n", - "\n", - " # Maintain rank incrementally.\n", - " model.Add(machine_ranks[j] == machine_ranks[i] + 1).OnlyEnforceIf(lit)\n", - "\n", - " # Compute the transition time if task j is the successor of task i.\n", - " if machine_resources[i] != machine_resources[j]:\n", - " transition_time = 3\n", - " switch_literals.append(lit)\n", - " else:\n", - " transition_time = 0\n", - " # We add the reified transition to link the literals with the times\n", - " # of the tasks.\n", - " model.Add(machine_starts[j] == machine_ends[i] +\n", - " transition_time).OnlyEnforceIf(lit)\n", - " if arcs:\n", - " model.AddCircuit(arcs)\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Objective.\n", - "makespan = model.NewIntVar(0, horizon, 'makespan')\n", - "model.AddMaxEquality(makespan, job_ends)\n", - "makespan_weight = 1\n", - "transition_weight = 5\n", - "model.Minimize(makespan * makespan_weight +\n", - " sum(switch_literals) * transition_weight)\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Write problem to file.\n", - "if output_proto:\n", - " print('Writing proto to %s' % output_proto)\n", - " with open(output_proto, 'w') as text_file:\n", - " text_file.write(str(model))\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Solve.\n", - "solver = cp_model.CpSolver()\n", - "solver.parameters.max_time_in_seconds = 60 * 60 * 2\n", - "if parameters:\n", - " text_format.Merge(parameters, solver.parameters)\n", - "solution_printer = SolutionPrinter(makespan)\n", - "status = solver.Solve(model, solution_printer)\n", - "\n", - "#----------------------------------------------------------------------------\n", - "# Print solution.\n", - "if status == cp_model.FEASIBLE or status == cp_model.OPTIMAL:\n", + " #----------------------------------------------------------------------------\n", + " # Scan the jobs and create the relevant variables and intervals.\n", " for job_id in all_jobs:\n", - " for task_id in range(len(jobs[job_id])):\n", - " start_value = solver.Value(job_starts[(job_id, task_id)])\n", - " machine = 0\n", - " duration = 0\n", - " select = 0\n", - " rank = -1\n", + " job = jobs[job_id]\n", + " num_tasks = len(job)\n", + " previous_end = None\n", + " for task_id in range(num_tasks):\n", + " task = job[task_id]\n", "\n", - " for alt_id in range(len(jobs[job_id][task_id])):\n", + " min_duration = task[0][0]\n", + " max_duration = task[0][0]\n", + "\n", + " num_alternatives = len(task)\n", + " all_alternatives = range(num_alternatives)\n", + "\n", + " for alt_id in range(1, num_alternatives):\n", + " alt_duration = task[alt_id][0]\n", + " min_duration = min(min_duration, alt_duration)\n", + " max_duration = max(max_duration, alt_duration)\n", + "\n", + " # Create main interval for the task.\n", + " suffix_name = '_j%i_t%i' % (job_id, task_id)\n", + " start = model.NewIntVar(0, horizon, 'start' + suffix_name)\n", + " duration = model.NewIntVar(min_duration, max_duration,\n", + " 'duration' + suffix_name)\n", + " end = model.NewIntVar(0, horizon, 'end' + suffix_name)\n", + "\n", + " # Store the start for the solution.\n", + " job_starts[(job_id, task_id)] = start\n", + "\n", + " # Add precedence with previous task in the same job.\n", + " if previous_end:\n", + " model.Add(start >= previous_end)\n", + " previous_end = end\n", + "\n", + " # Create alternative intervals.\n", + " l_presences = []\n", + " for alt_id in all_alternatives:\n", + " ### add to link interval with eqp constraint.\n", + " ### process time = -1 cannot be processed at this machine.\n", " if jobs[job_id][task_id][alt_id][0] == -1:\n", " continue\n", + " alt_suffix = '_j%i_t%i_a%i' % (job_id, task_id, alt_id)\n", + " l_presence = model.NewBoolVar('presence' + alt_suffix)\n", + " l_start = model.NewIntVar(0, horizon, 'start' + alt_suffix)\n", + " l_duration = task[alt_id][0]\n", + " l_end = model.NewIntVar(0, horizon, 'end' + alt_suffix)\n", + " l_interval = model.NewOptionalIntervalVar(\n", + " l_start, l_duration, l_end, l_presence, 'interval' + alt_suffix)\n", + " l_rank = model.NewIntVar(-1, num_jobs, 'rank' + alt_suffix)\n", + " l_presences.append(l_presence)\n", + " l_machine = task[alt_id][1]\n", + " l_type = task[alt_id][2]\n", "\n", - " if solver.BooleanValue(job_presences[(job_id, task_id, alt_id)]):\n", - " duration = jobs[job_id][task_id][alt_id][0]\n", - " machine = jobs[job_id][task_id][alt_id][1]\n", - " select = alt_id\n", - " rank = solver.Value(job_ranks[(job_id, task_id, alt_id)])\n", + " # Link the master variables with the local ones.\n", + " model.Add(start == l_start).OnlyEnforceIf(l_presence)\n", + " model.Add(duration == l_duration).OnlyEnforceIf(l_presence)\n", + " model.Add(end == l_end).OnlyEnforceIf(l_presence)\n", "\n", - " print(\n", - " ' Job %i starts at %i (alt %i, duration %i) with rank %i on machine %i'\n", - " % (job_id, start_value, select, duration, rank, machine))\n", + " # Add the local variables to the right machine.\n", + " intervals_per_machines[l_machine].append(l_interval)\n", + " starts_per_machines[l_machine].append(l_start)\n", + " ends_per_machines[l_machine].append(l_end)\n", + " presences_per_machines[l_machine].append(l_presence)\n", + " resources_per_machines[l_machine].append(l_type)\n", + " ranks_per_machines[l_machine].append(l_rank)\n", "\n", - " print('Solve status: %s' % solver.StatusName(status))\n", - " print('Objective value: %i' % solver.ObjectiveValue())\n", - " print('Makespan: %i' % solver.Value(makespan))\n", + " # Store the variables for the solution.\n", + " job_presences[(job_id, task_id, alt_id)] = l_presence\n", + " job_ranks[(job_id, task_id, alt_id)] = l_rank\n", + "\n", + " # Only one machine can process each lot.\n", + " model.Add(sum(l_presences) == 1)\n", + "\n", + " job_ends.append(previous_end)\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Create machines constraints nonoverlap process\n", + " for machine_id in all_machines:\n", + " intervals = intervals_per_machines[machine_id]\n", + " if len(intervals) > 1:\n", + " model.AddNoOverlap(intervals)\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Transition times and transition costs using a circuit constraint.\n", + " switch_literals = []\n", + " for machine_id in all_machines:\n", + " machine_starts = starts_per_machines[machine_id]\n", + " machine_ends = ends_per_machines[machine_id]\n", + " machine_presences = presences_per_machines[machine_id]\n", + " machine_resources = resources_per_machines[machine_id]\n", + " machine_ranks = ranks_per_machines[machine_id]\n", + " intervals = intervals_per_machines[machine_id]\n", + " arcs = []\n", + " num_machine_tasks = len(machine_starts)\n", + " all_machine_tasks = range(num_machine_tasks)\n", + "\n", + " for i in all_machine_tasks:\n", + " # Initial arc from the dummy node (0) to a task.\n", + " start_lit = model.NewBoolVar('')\n", + " arcs.append([0, i + 1, start_lit])\n", + " # If this task is the first, set both rank and start to 0.\n", + " model.Add(machine_ranks[i] == 0).OnlyEnforceIf(start_lit)\n", + " model.Add(machine_starts[i] == 0).OnlyEnforceIf(start_lit)\n", + " # Final arc from an arc to the dummy node.\n", + " arcs.append([i + 1, 0, model.NewBoolVar('')])\n", + " # Self arc if the task is not performed.\n", + " arcs.append([i + 1, i + 1, machine_presences[i].Not()])\n", + " model.Add(machine_ranks[i] == -1).OnlyEnforceIf(\n", + " machine_presences[i].Not())\n", + "\n", + " for j in all_machine_tasks:\n", + " if i == j:\n", + " continue\n", + "\n", + " lit = model.NewBoolVar('%i follows %i' % (j, i))\n", + " arcs.append([i + 1, j + 1, lit])\n", + " model.AddImplication(lit, machine_presences[i])\n", + " model.AddImplication(lit, machine_presences[j])\n", + "\n", + " # Maintain rank incrementally.\n", + " model.Add(machine_ranks[j] == machine_ranks[i] + 1).OnlyEnforceIf(lit)\n", + "\n", + " # Compute the transition time if task j is the successor of task i.\n", + " if machine_resources[i] != machine_resources[j]:\n", + " transition_time = 3\n", + " switch_literals.append(lit)\n", + " else:\n", + " transition_time = 0\n", + " # We add the reified transition to link the literals with the times\n", + " # of the tasks.\n", + " model.Add(machine_starts[j] == machine_ends[i] +\n", + " transition_time).OnlyEnforceIf(lit)\n", + " if arcs:\n", + " model.AddCircuit(arcs)\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Objective.\n", + " makespan = model.NewIntVar(0, horizon, 'makespan')\n", + " model.AddMaxEquality(makespan, job_ends)\n", + " makespan_weight = 1\n", + " transition_weight = 5\n", + " model.Minimize(makespan * makespan_weight +\n", + " sum(switch_literals) * transition_weight)\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Write problem to file.\n", + " if output_proto:\n", + " print('Writing proto to %s' % output_proto)\n", + " with open(output_proto, 'w') as text_file:\n", + " text_file.write(str(model))\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Solve.\n", + " solver = cp_model.CpSolver()\n", + " solver.parameters.max_time_in_seconds = 60 * 60 * 2\n", + " if parameters:\n", + " text_format.Merge(parameters, solver.parameters)\n", + " solution_printer = SolutionPrinter(makespan)\n", + " status = solver.Solve(model, solution_printer)\n", + "\n", + " #----------------------------------------------------------------------------\n", + " # Print solution.\n", + " if status == cp_model.FEASIBLE or status == cp_model.OPTIMAL:\n", + " for job_id in all_jobs:\n", + " for task_id in range(len(jobs[job_id])):\n", + " start_value = solver.Value(job_starts[(job_id, task_id)])\n", + " machine = 0\n", + " duration = 0\n", + " select = 0\n", + " rank = -1\n", + "\n", + " for alt_id in range(len(jobs[job_id][task_id])):\n", + " if jobs[job_id][task_id][alt_id][0] == -1:\n", + " continue\n", + "\n", + " if solver.BooleanValue(job_presences[(job_id, task_id, alt_id)]):\n", + " duration = jobs[job_id][task_id][alt_id][0]\n", + " machine = jobs[job_id][task_id][alt_id][1]\n", + " select = alt_id\n", + " rank = solver.Value(job_ranks[(job_id, task_id, alt_id)])\n", + "\n", + " print(\n", + " ' Job %i starts at %i (alt %i, duration %i) with rank %i on machine %i'\n", + " % (job_id, start_value, select, duration, rank, machine))\n", + "\n", + " print('Solve status: %s' % solver.StatusName(status))\n", + " print('Objective value: %i' % solver.ObjectiveValue())\n", + " print('Makespan: %i' % solver.Value(makespan))\n", + "\n", + "\n", + "main(PARSER.parse_args())\n", "\n" ] } diff --git a/examples/notebook/contrib/school_scheduling_sat.ipynb b/examples/notebook/contrib/school_scheduling_sat.ipynb index ec1b5717c1..09199a9195 100644 --- a/examples/notebook/contrib/school_scheduling_sat.ipynb +++ b/examples/notebook/contrib/school_scheduling_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -211,38 +211,42 @@ " print('Found Solution!')\n", "\n", "\n", - "# DATA\n", - "subjects = ['English', 'Math', 'History']\n", - "levels = ['1-', '2-', '3-']\n", - "sections = ['A']\n", - "teachers = ['Mario', 'Elvis', 'Donald', 'Ian']\n", - "teachers_work_hours = [18, 12, 12, 18]\n", - "working_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']\n", - "periods = ['08:00-09:30', '09:45-11:15', '11:30-13:00']\n", - "curriculum = {\n", - " ('1-', 'English'): 3,\n", - " ('1-', 'Math'): 3,\n", - " ('1-', 'History'): 2,\n", - " ('2-', 'English'): 4,\n", - " ('2-', 'Math'): 2,\n", - " ('2-', 'History'): 2,\n", - " ('3-', 'English'): 2,\n", - " ('3-', 'Math'): 4,\n", - " ('3-', 'History'): 2\n", - "}\n", + "def main():\n", + " # DATA\n", + " subjects = ['English', 'Math', 'History']\n", + " levels = ['1-', '2-', '3-']\n", + " sections = ['A']\n", + " teachers = ['Mario', 'Elvis', 'Donald', 'Ian']\n", + " teachers_work_hours = [18, 12, 12, 18]\n", + " working_days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']\n", + " periods = ['08:00-09:30', '09:45-11:15', '11:30-13:00']\n", + " curriculum = {\n", + " ('1-', 'English'): 3,\n", + " ('1-', 'Math'): 3,\n", + " ('1-', 'History'): 2,\n", + " ('2-', 'English'): 4,\n", + " ('2-', 'Math'): 2,\n", + " ('2-', 'History'): 2,\n", + " ('3-', 'English'): 2,\n", + " ('3-', 'Math'): 4,\n", + " ('3-', 'History'): 2\n", + " }\n", "\n", - "# Subject -> List of teachers who can teach it\n", - "specialties_idx_inverse = [\n", - " [1, 3], # English -> Elvis & Ian\n", - " [0, 3], # Math -> Mario & Ian\n", - " [2, 3] # History -> Donald & Ian\n", - "]\n", + " # Subject -> List of teachers who can teach it\n", + " specialties_idx_inverse = [\n", + " [1, 3], # English -> Elvis & Ian\n", + " [0, 3], # Math -> Mario & Ian\n", + " [2, 3] # History -> Donald & Ian\n", + " ]\n", "\n", - "problem = SchoolSchedulingProblem(\n", - " subjects, teachers, curriculum, specialties_idx_inverse, working_days,\n", - " periods, levels, sections, teachers_work_hours)\n", - "solver = SchoolSchedulingSatSolver(problem)\n", - "solver.solve()\n", + " problem = SchoolSchedulingProblem(\n", + " subjects, teachers, curriculum, specialties_idx_inverse, working_days,\n", + " periods, levels, sections, teachers_work_hours)\n", + " solver = SchoolSchedulingSatSolver(problem)\n", + " solver.solve()\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/secret_santa.ipynb b/examples/notebook/contrib/secret_santa.ipynb index 3fc3435bbb..c58cf4256b 100644 --- a/examples/notebook/contrib/secret_santa.ipynb +++ b/examples/notebook/contrib/secret_santa.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Secret Santa problem in Google CP Solver.\n", "\n", @@ -133,58 +118,70 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Secret Santa problem')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Secret Santa problem')\n", "\n", - "#\n", - "# data\n", - "#\n", - "family = [1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 4, 4]\n", - "num_families = max(family)\n", - "n = len(family)\n", + " #\n", + " # data\n", + " #\n", + " family = [1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 4, 4]\n", + " num_families = max(family)\n", + " n = len(family)\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = [solver.IntVar(0, n - 1, 'x[%i]' % i) for i in range(n)]\n", + " #\n", + " # declare variables\n", + " #\n", + " x = [solver.IntVar(0, n - 1, 'x[%i]' % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", "\n", - "# Can't be one own's Secret Santa\n", - "# Ensure that there are no fix-point in the array\n", - "for i in range(n):\n", - " solver.Add(x[i] != i)\n", + " # Can't be one own's Secret Santa\n", + " # Ensure that there are no fix-point in the array\n", + " for i in range(n):\n", + " solver.Add(x[i] != i)\n", "\n", - "# No Secret Santa to a person in the same family\n", - "for i in range(n):\n", - " solver.Add(family[i] != solver.Element(family, x[i]))\n", + " # No Secret Santa to a person in the same family\n", + " for i in range(n):\n", + " solver.Add(family[i] != solver.Element(family, x[i]))\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_SIMPLE, solver.INT_VALUE_SIMPLE)\n", "\n", - "solver.NewSearch(db)\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", + " solver.NewSearch(db)\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", - "print('num_solutions:', num_solutions)\n", - "print('failures:', solver.Failures())\n", - "print('branches:', solver.Branches())\n", - "print('WallTime:', solver.WallTime(), 'ms')\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/secret_santa2.ipynb b/examples/notebook/contrib/secret_santa2.ipynb index c4c75b4717..b86cbab56f 100644 --- a/examples/notebook/contrib/secret_santa2.ipynb +++ b/examples/notebook/contrib/secret_santa2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Secret Santa problem II in Google CP Solver.\n", "\n", @@ -134,157 +119,173 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(singe=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Secret Santa problem II')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Secret Santa problem II')\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "#\n", - "# The matrix version of earlier rounds.\n", - "# M means that no earlier Santa has been assigned.\n", - "# Note: Ryan and Mia has the same recipient for years 3 and 4,\n", - "# and Ella and John has for year 4.\n", - "# This seems to be caused by modification of\n", - "# original data.\n", - "#\n", - "n_no_single = 8\n", - "M = n_no_single + 1\n", - "rounds_no_single = [\n", - " # N A R M El J L Ev\n", - " [0, M, 3, M, 1, 4, M, 2], # Noah\n", - " [M, 0, 4, 2, M, 3, M, 1], # Ava\n", - " [M, 2, 0, M, 1, M, 3, 4], # Ryan\n", - " [M, 1, M, 0, 2, M, 3, 4], # Mia\n", - " [M, 4, M, 3, 0, M, 1, 2], # Ella\n", - " [1, 4, 3, M, M, 0, 2, M], # John\n", - " [M, 3, M, 2, 4, 1, 0, M], # Lily\n", - " [4, M, 3, 1, M, 2, M, 0] # Evan\n", - "]\n", + " #\n", + " # The matrix version of earlier rounds.\n", + " # M means that no earlier Santa has been assigned.\n", + " # Note: Ryan and Mia has the same recipient for years 3 and 4,\n", + " # and Ella and John has for year 4.\n", + " # This seems to be caused by modification of\n", + " # original data.\n", + " #\n", + " n_no_single = 8\n", + " M = n_no_single + 1\n", + " rounds_no_single = [\n", + " # N A R M El J L Ev\n", + " [0, M, 3, M, 1, 4, M, 2], # Noah\n", + " [M, 0, 4, 2, M, 3, M, 1], # Ava\n", + " [M, 2, 0, M, 1, M, 3, 4], # Ryan\n", + " [M, 1, M, 0, 2, M, 3, 4], # Mia\n", + " [M, 4, M, 3, 0, M, 1, 2], # Ella\n", + " [1, 4, 3, M, M, 0, 2, M], # John\n", + " [M, 3, M, 2, 4, 1, 0, M], # Lily\n", + " [4, M, 3, 1, M, 2, M, 0] # Evan\n", + " ]\n", "\n", - "#\n", - "# Rounds with a single person (fake data)\n", - "#\n", - "n_with_single = 9\n", - "M = n_with_single + 1\n", - "rounds_single = [\n", - " # N A R M El J L Ev S\n", - " [0, M, 3, M, 1, 4, M, 2, 2], # Noah\n", - " [M, 0, 4, 2, M, 3, M, 1, 1], # Ava\n", - " [M, 2, 0, M, 1, M, 3, 4, 4], # Ryan\n", - " [M, 1, M, 0, 2, M, 3, 4, 3], # Mia\n", - " [M, 4, M, 3, 0, M, 1, 2, M], # Ella\n", - " [1, 4, 3, M, M, 0, 2, M, M], # John\n", - " [M, 3, M, 2, 4, 1, 0, M, M], # Lily\n", - " [4, M, 3, 1, M, 2, M, 0, M], # Evan\n", - " [1, 2, 3, 4, M, 2, M, M, 0] # Single\n", - "]\n", + " #\n", + " # Rounds with a single person (fake data)\n", + " #\n", + " n_with_single = 9\n", + " M = n_with_single + 1\n", + " rounds_single = [\n", + " # N A R M El J L Ev S\n", + " [0, M, 3, M, 1, 4, M, 2, 2], # Noah\n", + " [M, 0, 4, 2, M, 3, M, 1, 1], # Ava\n", + " [M, 2, 0, M, 1, M, 3, 4, 4], # Ryan\n", + " [M, 1, M, 0, 2, M, 3, 4, 3], # Mia\n", + " [M, 4, M, 3, 0, M, 1, 2, M], # Ella\n", + " [1, 4, 3, M, M, 0, 2, M, M], # John\n", + " [M, 3, M, 2, 4, 1, 0, M, M], # Lily\n", + " [4, M, 3, 1, M, 2, M, 0, M], # Evan\n", + " [1, 2, 3, 4, M, 2, M, M, 0] # Single\n", + " ]\n", "\n", - "if single == 1:\n", - " n = n_with_single\n", - " Noah, Ava, Ryan, Mia, Ella, John, Lily, Evan, Single = list(range(n))\n", - " rounds = rounds_single\n", - "else:\n", - " n = n_no_single\n", - " Noah, Ava, Ryan, Mia, Ella, John, Lily, Evan = list(range(n))\n", - " rounds = rounds_no_single\n", + " if single == 1:\n", + " n = n_with_single\n", + " Noah, Ava, Ryan, Mia, Ella, John, Lily, Evan, Single = list(range(n))\n", + " rounds = rounds_single\n", + " else:\n", + " n = n_no_single\n", + " Noah, Ava, Ryan, Mia, Ella, John, Lily, Evan = list(range(n))\n", + " rounds = rounds_no_single\n", "\n", - "M = n + 1\n", + " M = n + 1\n", "\n", - "persons = [\n", - " 'Noah', 'Ava', 'Ryan', 'Mia', 'Ella', 'John', 'Lily', 'Evan', 'Single'\n", - "]\n", + " persons = [\n", + " 'Noah', 'Ava', 'Ryan', 'Mia', 'Ella', 'John', 'Lily', 'Evan', 'Single'\n", + " ]\n", "\n", - "spouses = [\n", - " Ava, # Noah\n", - " Noah, # Ava\n", - " Mia, # Rya\n", - " Ryan, # Mia\n", - " John, # Ella\n", - " Ella, # John\n", - " Evan, # Lily\n", - " Lily, # Evan\n", - " -1 # Single has no spouse\n", - "]\n", + " spouses = [\n", + " Ava, # Noah\n", + " Noah, # Ava\n", + " Mia, # Rya\n", + " Ryan, # Mia\n", + " John, # Ella\n", + " Ella, # John\n", + " Evan, # Lily\n", + " Lily, # Evan\n", + " -1 # Single has no spouse\n", + " ]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "santas = [solver.IntVar(0, n - 1, 'santas[%i]' % i) for i in range(n)]\n", - "santa_distance = [\n", - " solver.IntVar(0, M, 'santa_distance[%i]' % i) for i in range(n)\n", - "]\n", + " #\n", + " # declare variables\n", + " #\n", + " santas = [solver.IntVar(0, n - 1, 'santas[%i]' % i) for i in range(n)]\n", + " santa_distance = [\n", + " solver.IntVar(0, M, 'santa_distance[%i]' % i) for i in range(n)\n", + " ]\n", "\n", - "# total of 'distance', to maximize\n", - "z = solver.IntVar(0, n * n * n, 'z')\n", + " # total of 'distance', to maximize\n", + " z = solver.IntVar(0, n * n * n, 'z')\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(santas))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(santas))\n", "\n", - "solver.Add(z == solver.Sum(santa_distance))\n", + " solver.Add(z == solver.Sum(santa_distance))\n", "\n", - "# Can't be one own's Secret Santa\n", - "# (i.e. ensure that there are no fix-point in the array.)\n", - "for i in range(n):\n", - " solver.Add(santas[i] != i)\n", - "\n", - "# no Santa for a spouses\n", - "for i in range(n):\n", - " if spouses[i] > -1:\n", - " solver.Add(santas[i] != spouses[i])\n", - "\n", - "# optimize 'distance' to earlier rounds:\n", - "for i in range(n):\n", - " solver.Add(santa_distance[i] == solver.Element(rounds[i], santas[i]))\n", - "\n", - "# cannot be a Secret Santa for the same person\n", - "# two years in a row.\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if rounds[i][j] == 1:\n", - " solver.Add(santas[i] != j)\n", - "\n", - "# objective\n", - "objective = solver.Maximize(z, 1)\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "db = solver.Phase(santas, 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('total distances:', z.Value())\n", - " print('santas:', [santas[i].Value() for i in range(n)])\n", + " # Can't be one own's Secret Santa\n", + " # (i.e. ensure that there are no fix-point in the array.)\n", " for i in range(n):\n", - " print('%s\\tis a Santa to %s (distance %i)' % \\\n", - " (persons[i],\n", - " persons[santas[i].Value()],\n", - " santa_distance[i].Value()))\n", - " # print 'distance:', [santa_distance[i].Value()\n", - " # for i in range(n)]\n", - " print()\n", + " solver.Add(santas[i] != i)\n", "\n", - "print('num_solutions:', num_solutions)\n", - "print('failures:', solver.Failures())\n", - "print('branches:', solver.Branches())\n", - "print('WallTime:', solver.WallTime(), 'ms')\n", + " # no Santa for a spouses\n", + " for i in range(n):\n", + " if spouses[i] > -1:\n", + " solver.Add(santas[i] != spouses[i])\n", "\n", - "single = 0\n" + " # optimize 'distance' to earlier rounds:\n", + " for i in range(n):\n", + " solver.Add(santa_distance[i] == solver.Element(rounds[i], santas[i]))\n", + "\n", + " # cannot be a Secret Santa for the same person\n", + " # two years in a row.\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if rounds[i][j] == 1:\n", + " solver.Add(santas[i] != j)\n", + "\n", + " # objective\n", + " objective = solver.Maximize(z, 1)\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " db = solver.Phase(santas, 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('total distances:', z.Value())\n", + " print('santas:', [santas[i].Value() for i in range(n)])\n", + " for i in range(n):\n", + " print('%s\\tis a Santa to %s (distance %i)' % \\\n", + " (persons[i],\n", + " persons[santas[i].Value()],\n", + " santa_distance[i].Value()))\n", + " # print 'distance:', [santa_distance[i].Value()\n", + " # 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", + "\n", + "single = 0\n", + "print('Secret Santas without single')\n", + "main(single)\n", + "print('\\nSecret Santas with single:')\n", + "single = 1\n", + "main(single)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/send_more_money_any_base.ipynb b/examples/notebook/contrib/send_more_money_any_base.ipynb index a747ec6968..e0b99b5e2e 100644 --- a/examples/notebook/contrib/send_more_money_any_base.ipynb +++ b/examples/notebook/contrib/send_more_money_any_base.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " SEND+MORE=MONEY in 'any' base in Google CP Solver.\n", "\n", @@ -115,66 +100,83 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(base=10):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Send most money')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Send most money')\n", "\n", - "# data\n", - "print('base:', base)\n", + " # data\n", + " print('base:', base)\n", "\n", - "# declare variables\n", - "s = solver.IntVar(0, base - 1, 's')\n", - "e = solver.IntVar(0, base - 1, 'e')\n", - "n = solver.IntVar(0, base - 1, 'n')\n", - "d = solver.IntVar(0, base - 1, 'd')\n", - "m = solver.IntVar(0, base - 1, 'm')\n", - "o = solver.IntVar(0, base - 1, 'o')\n", - "r = solver.IntVar(0, base - 1, 'r')\n", - "y = solver.IntVar(0, base - 1, 'y')\n", + " # declare variables\n", + " s = solver.IntVar(0, base - 1, 's')\n", + " e = solver.IntVar(0, base - 1, 'e')\n", + " n = solver.IntVar(0, base - 1, 'n')\n", + " d = solver.IntVar(0, base - 1, 'd')\n", + " m = solver.IntVar(0, base - 1, 'm')\n", + " o = solver.IntVar(0, base - 1, 'o')\n", + " r = solver.IntVar(0, base - 1, 'r')\n", + " y = solver.IntVar(0, base - 1, 'y')\n", "\n", - "x = [s, e, n, d, m, o, r, y]\n", + " x = [s, e, n, d, m, o, r, y]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", - "solver.Add(\n", - " s * base**3 + e * base**2 + n * base + d + m * base**3 + o * base**2 +\n", - " r * base + e == m * base**4 + o * base**3 + n * base**2 + e * base + y,)\n", - "solver.Add(s > 0)\n", - "solver.Add(m > 0)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", + " solver.Add(\n", + " s * base**3 + e * base**2 + n * base + d + m * base**3 + o * base**2 +\n", + " r * base + e == m * base**4 + o * base**3 + n * base**2 + e * base + y,)\n", + " solver.Add(s > 0)\n", + " solver.Add(m > 0)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", "\n", - "collector = solver.AllSolutionCollector(solution)\n", + " collector = solver.AllSolutionCollector(solution)\n", "\n", - "solver.Solve(\n", - " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MAX_VALUE),\n", - " [collector])\n", + " solver.Solve(\n", + " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MAX_VALUE),\n", + " [collector])\n", "\n", - "num_solutions = collector.SolutionCount()\n", - "money_val = 0\n", - "for s in range(num_solutions):\n", - " print('x:', [collector.Value(s, x[i]) for i in range(len(x))])\n", + " num_solutions = collector.SolutionCount()\n", + " money_val = 0\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", + " 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", - "base = 10\n" + "\n", + "base = 10\n", + "# for base in range(10,30):\n", + "# main(base)\n", + "if len(sys.argv) > 1:\n", + " base = int(sys.argv[1])\n", + "\n", + "main(base)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/send_most_money.ipynb b/examples/notebook/contrib/send_most_money.ipynb index c653950fb7..8d9df8501d 100644 --- a/examples/notebook/contrib/send_most_money.ipynb +++ b/examples/notebook/contrib/send_most_money.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " SEND+MOST=MONEY in Google CP Solver.\n", "\n", @@ -112,77 +97,94 @@ " Also see my other Google CP Solver models:\n", " http://www.hakank.org/google_or_tools/\n", "\n", - "\"\"\"\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(MONEY=0):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Send most money')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Send most money')\n", "\n", - "# data\n", + " # data\n", "\n", - "# declare variables\n", - "s = solver.IntVar(0, 9, 's')\n", - "e = solver.IntVar(0, 9, 'e')\n", - "n = solver.IntVar(0, 9, 'n')\n", - "d = solver.IntVar(0, 9, 'd')\n", - "m = solver.IntVar(0, 9, 'm')\n", - "o = solver.IntVar(0, 9, 'o')\n", - "t = solver.IntVar(0, 9, 't')\n", - "y = solver.IntVar(0, 9, 'y')\n", - "money = solver.IntVar(0, 100000, 'money')\n", + " # declare variables\n", + " s = solver.IntVar(0, 9, 's')\n", + " e = solver.IntVar(0, 9, 'e')\n", + " n = solver.IntVar(0, 9, 'n')\n", + " d = solver.IntVar(0, 9, 'd')\n", + " m = solver.IntVar(0, 9, 'm')\n", + " o = solver.IntVar(0, 9, 'o')\n", + " t = solver.IntVar(0, 9, 't')\n", + " y = solver.IntVar(0, 9, 'y')\n", + " money = solver.IntVar(0, 100000, 'money')\n", "\n", - "x = [s, e, n, d, m, o, t, y]\n", + " x = [s, e, n, d, m, o, t, y]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "if MONEY > 0:\n", - " solver.Add(money == MONEY)\n", + " #\n", + " # constraints\n", + " #\n", + " if MONEY > 0:\n", + " solver.Add(money == MONEY)\n", "\n", - "solver.Add(solver.AllDifferent(x))\n", - "solver.Add(money == m * 10000 + o * 1000 + n * 100 + e * 10 + y)\n", - "solver.Add(money > 0)\n", - "solver.Add(1000 * s + 100 * e + 10 * n + d + 1000 * m + 100 * o + 10 * s +\n", - " t == money)\n", - "solver.Add(s > 0)\n", - "solver.Add(m > 0)\n", + " solver.Add(solver.AllDifferent(x))\n", + " solver.Add(money == m * 10000 + o * 1000 + n * 100 + e * 10 + y)\n", + " solver.Add(money > 0)\n", + " solver.Add(1000 * s + 100 * e + 10 * n + d + 1000 * m + 100 * o + 10 * s +\n", + " t == money)\n", + " solver.Add(s > 0)\n", + " solver.Add(m > 0)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.Add(money)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.Add(money)\n", "\n", - "collector = solver.AllSolutionCollector(solution)\n", - "objective = solver.Maximize(money, 100)\n", - "cargs = [collector]\n", - "if MONEY == 0:\n", - " objective = solver.Maximize(money, 1)\n", - " cargs.extend([objective])\n", + " collector = solver.AllSolutionCollector(solution)\n", + " objective = solver.Maximize(money, 100)\n", + " cargs = [collector]\n", + " if MONEY == 0:\n", + " objective = solver.Maximize(money, 1)\n", + " cargs.extend([objective])\n", "\n", - "solver.Solve(\n", - " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MAX_VALUE),\n", - " cargs)\n", + " solver.Solve(\n", + " solver.Phase(x, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MAX_VALUE),\n", + " cargs)\n", "\n", - "num_solutions = collector.SolutionCount()\n", - "money_val = 0\n", - "for s in range(num_solutions):\n", - " print('x:', [collector.Value(s, x[i]) for i in range(len(x))])\n", - " money_val = collector.Value(s, money)\n", - " print('money:', money_val)\n", - " print()\n", + " num_solutions = collector.SolutionCount()\n", + " money_val = 0\n", + " for s in range(num_solutions):\n", + " print('x:', [collector.Value(s, x[i]) for i in range(len(x))])\n", + " money_val = collector.Value(s, money)\n", + " print('money:', money_val)\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", + " print('num_solutions:', num_solutions)\n", + " print('failures:', solver.Failures())\n", + " print('branches:', solver.Branches())\n", + " print('WallTime:', solver.WallTime())\n", "\n", - "if MONEY == 0:\n", - " return money_val\n", + " if MONEY == 0:\n", + " return money_val\n", + "\n", + "\n", + "# First get the maximised MONEY, and then show all solutions for\n", + "# this value\n", + "print('Minimize money...')\n", + "money = main(0)\n", + "print('\\nCheck all solutions for money=%i' % money)\n", + "main(money)\n", "\n" ] } diff --git a/examples/notebook/contrib/seseman.ipynb b/examples/notebook/contrib/seseman.ipynb index d81dcb99f5..589e40f03a 100644 --- a/examples/notebook/contrib/seseman.ipynb +++ b/examples/notebook/contrib/seseman.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Seseman Convent problem in Google CP Solver.\n", "\n", @@ -127,83 +112,95 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Seseman Convent problem\")\n", + "def main(unused_argv):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Seseman Convent problem\")\n", "\n", - "# data\n", - "n = 3\n", - "border_sum = n * n\n", + " # data\n", + " n = 3\n", + " border_sum = n * n\n", "\n", - "# declare variables\n", - "total_sum = solver.IntVar(1, n * n * n * n, \"total_sum\")\n", - "# x[0..n-1,0..n-1]\n", - "x = {}\n", - "for i in range(n):\n", - " for j in range(n):\n", - " x[(i, j)] = solver.IntVar(0, n * n, \"x %i %i\" % (i, j))\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "# zero all middle cells\n", - "for i in range(1, n - 1):\n", - " for j in range(1, n - 1):\n", - " solver.Add(x[(i, j)] == 0)\n", - "\n", - "# all borders must be >= 1\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if i == 0 or j == 0 or i == n - 1 or j == n - 1:\n", - " solver.Add(x[(i, j)] >= 1)\n", - "\n", - "# sum the borders (border_sum)\n", - "solver.Add(solver.Sum([x[(i, 0)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(i, n - 1)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(0, i)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(n - 1, i)] for i in range(n)]) == border_sum)\n", - "\n", - "# total\n", - "solver.Add(\n", - " solver.Sum([x[(i, j)] for i in range(n) for j in range(n)]) == total_sum)\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.Add(total_sum)\n", - "\n", - "# all solutions\n", - "collector = solver.AllSolutionCollector(solution)\n", - "# search_log = solver.SearchLog(100, total_sum)\n", - "solver.Solve(\n", - " solver.Phase([x[(i, j)] for i in range(n) for j in range(n)],\n", - " solver.CHOOSE_PATH, solver.ASSIGN_MIN_VALUE), [collector])\n", - "#[collector, search_log])\n", - "\n", - "num_solutions = collector.SolutionCount()\n", - "# print \"x:\", x\n", - "print(\"num_solutions:\", num_solutions)\n", - "print()\n", - "for s in range(num_solutions):\n", - " # print [collector.Value(s, x[(i,j)])\n", - " # for i in range(n) for j in range(n)]\n", - " print(\"total_sum:\", collector.Value(s, total_sum))\n", + " # declare variables\n", + " total_sum = solver.IntVar(1, n * n * n * n, \"total_sum\")\n", + " # x[0..n-1,0..n-1]\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(collector.Value(s, x[(i, j)]), end=\" \")\n", - " print()\n", - " print()\n", + " x[(i, j)] = solver.IntVar(0, n * n, \"x %i %i\" % (i, j))\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", - "print(\"num_solutions:\", num_solutions)\n", + " #\n", + " # constraints\n", + " #\n", + " # zero all middle cells\n", + " for i in range(1, n - 1):\n", + " for j in range(1, n - 1):\n", + " solver.Add(x[(i, j)] == 0)\n", + "\n", + " # all borders must be >= 1\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if i == 0 or j == 0 or i == n - 1 or j == n - 1:\n", + " solver.Add(x[(i, j)] >= 1)\n", + "\n", + " # sum the borders (border_sum)\n", + " solver.Add(solver.Sum([x[(i, 0)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(i, n - 1)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(0, i)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(n - 1, i)] for i in range(n)]) == border_sum)\n", + "\n", + " # total\n", + " solver.Add(\n", + " solver.Sum([x[(i, j)] for i in range(n) for j in range(n)]) == total_sum)\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.Add(total_sum)\n", + "\n", + " # all solutions\n", + " collector = solver.AllSolutionCollector(solution)\n", + " # search_log = solver.SearchLog(100, total_sum)\n", + " solver.Solve(\n", + " solver.Phase([x[(i, j)] for i in range(n) for j in range(n)],\n", + " solver.CHOOSE_PATH, solver.ASSIGN_MIN_VALUE), [collector])\n", + " #[collector, search_log])\n", + "\n", + " num_solutions = collector.SolutionCount()\n", + " # print \"x:\", x\n", + " print(\"num_solutions:\", num_solutions)\n", + " print()\n", + " for s in range(num_solutions):\n", + " # print [collector.Value(s, x[(i,j)])\n", + " # for i in range(n) for j in range(n)]\n", + " print(\"total_sum:\", collector.Value(s, total_sum))\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(collector.Value(s, 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", + " print(\"num_solutions:\", num_solutions)\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/seseman_b.ipynb b/examples/notebook/contrib/seseman_b.ipynb index 2f27f9ff75..cfb139fdb2 100644 --- a/examples/notebook/contrib/seseman_b.ipynb +++ b/examples/notebook/contrib/seseman_b.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Seseman Convent problem in Google CP Solver.\n", "\n", @@ -129,77 +114,89 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Seseman Convent problem\")\n", + "def main(unused_argv):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Seseman Convent problem\")\n", "\n", - "# data\n", - "n = 3\n", - "border_sum = n * n\n", + " # data\n", + " n = 3\n", + " border_sum = n * n\n", "\n", - "# declare variables\n", - "total_sum = solver.IntVar(1, n * n * n * n, \"total_sum\")\n", - "# x[0..n-1,0..n-1]\n", - "x = {}\n", - "for i in range(n):\n", - " for j in range(n):\n", - " x[(i, j)] = solver.IntVar(0, n * n, \"x %i %i\" % (i, j))\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "# zero all middle cells\n", - "for i in range(1, n - 1):\n", - " for j in range(1, n - 1):\n", - " solver.Add(x[(i, j)] == 0)\n", - "\n", - "# all borders must be >= 1\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if i == 0 or j == 0 or i == n - 1 or j == n - 1:\n", - " solver.Add(x[(i, j)] >= 1)\n", - "\n", - "# sum the borders (border_sum)\n", - "solver.Add(solver.Sum([x[(i, 0)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(i, n - 1)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(0, i)] for i in range(n)]) == border_sum)\n", - "solver.Add(solver.Sum([x[(n - 1, i)] for i in range(n)]) == border_sum)\n", - "\n", - "# total\n", - "solver.Add(\n", - " solver.Sum([x[(i, j)] for i in range(n) for j in range(n)]) == total_sum)\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.Add(total_sum)\n", - "\n", - "db = solver.Phase([x[(i, j)] for i in range(n) for j in range(n)],\n", - " solver.CHOOSE_PATH, solver.ASSIGN_MIN_VALUE)\n", - "\n", - "solver.NewSearch(db)\n", - "\n", - "num_solutions = 0\n", - "\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print(\"total_sum:\", total_sum.Value())\n", + " # declare variables\n", + " total_sum = solver.IntVar(1, n * n * n * n, \"total_sum\")\n", + " # x[0..n-1,0..n-1]\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(x[(i, j)].Value(), end=\" \")\n", - " print()\n", - " print()\n", + " x[(i, j)] = solver.IntVar(0, n * n, \"x %i %i\" % (i, j))\n", "\n", - "print(\"num_solutions:\", num_solutions)\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " #\n", + " # constraints\n", + " #\n", + " # zero all middle cells\n", + " for i in range(1, n - 1):\n", + " for j in range(1, n - 1):\n", + " solver.Add(x[(i, j)] == 0)\n", + "\n", + " # all borders must be >= 1\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if i == 0 or j == 0 or i == n - 1 or j == n - 1:\n", + " solver.Add(x[(i, j)] >= 1)\n", + "\n", + " # sum the borders (border_sum)\n", + " solver.Add(solver.Sum([x[(i, 0)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(i, n - 1)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(0, i)] for i in range(n)]) == border_sum)\n", + " solver.Add(solver.Sum([x[(n - 1, i)] for i in range(n)]) == border_sum)\n", + "\n", + " # total\n", + " solver.Add(\n", + " solver.Sum([x[(i, j)] for i in range(n) for j in range(n)]) == total_sum)\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.Add(total_sum)\n", + "\n", + " db = solver.Phase([x[(i, j)] for i in range(n) for j in range(n)],\n", + " solver.CHOOSE_PATH, solver.ASSIGN_MIN_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + "\n", + " num_solutions = 0\n", + "\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print(\"total_sum:\", total_sum.Value())\n", + " for i in range(n):\n", + " for j in range(n):\n", + " print(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())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering.ipynb b/examples/notebook/contrib/set_covering.ipynb index 727f3799e3..24db7224d9 100644 --- a/examples/notebook/contrib/set_covering.ipynb +++ b/examples/notebook/contrib/set_covering.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering in Google CP Solver.\n", "\n", @@ -104,62 +89,74 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set covering\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set covering\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "min_distance = 15\n", - "num_cities = 6\n", + " #\n", + " # data\n", + " #\n", + " min_distance = 15\n", + " num_cities = 6\n", "\n", - "distance = [[0, 10, 20, 30, 30, 20], [10, 0, 25, 35, 20, 10],\n", - " [20, 25, 0, 15, 30, 20], [30, 35, 15, 0, 15, 25],\n", - " [30, 20, 30, 15, 0, 14], [20, 10, 20, 25, 14, 0]]\n", + " distance = [[0, 10, 20, 30, 30, 20], [10, 0, 25, 35, 20, 10],\n", + " [20, 25, 0, 15, 30, 20], [30, 35, 15, 0, 15, 25],\n", + " [30, 20, 30, 15, 0, 14], [20, 10, 20, 25, 14, 0]]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_cities)]\n", + " #\n", + " # declare variables\n", + " #\n", + " x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_cities)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# objective to minimize\n", - "z = solver.Sum(x)\n", + " # objective to minimize\n", + " z = solver.Sum(x)\n", "\n", - "# ensure that all cities are covered\n", - "for i in range(num_cities):\n", - " b = [x[j] for j in range(num_cities) if distance[i][j] <= min_distance]\n", - " solver.Add(solver.SumGreaterOrEqual(b, 1))\n", + " # ensure that all cities are covered\n", + " for i in range(num_cities):\n", + " b = [x[j] for j in range(num_cities) if distance[i][j] <= min_distance]\n", + " solver.Add(solver.SumGreaterOrEqual(b, 1))\n", "\n", - "objective = solver.Minimize(z, 1)\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.AddObjective(z)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.AddObjective(z)\n", "\n", - "collector = solver.LastSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase(x + [z], solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", - " [collector, objective])\n", + " collector = solver.LastSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase(x + [z], solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", + " [collector, objective])\n", "\n", - "print(\"z:\", collector.ObjectiveValue(0))\n", - "print(\"x:\", [collector.Value(0, x[i]) for i in range(num_cities)])\n", + " print(\"z:\", collector.ObjectiveValue(0))\n", + " print(\"x:\", [collector.Value(0, x[i]) for i in range(num_cities)])\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering2.ipynb b/examples/notebook/contrib/set_covering2.ipynb index 97292309b9..cdd73cf3f2 100644 --- a/examples/notebook/contrib/set_covering2.ipynb +++ b/examples/notebook/contrib/set_covering2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering in Google CP Solver.\n", "\n", @@ -106,63 +91,75 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set covering\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set covering\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 8 # maximum number of corners\n", - "num_streets = 11 # number of connected streets\n", + " #\n", + " # data\n", + " #\n", + " n = 8 # maximum number of corners\n", + " num_streets = 11 # number of connected streets\n", "\n", - "# corners of each street\n", - "# Note: 1-based (handled below)\n", - "corner = [[1, 2], [2, 3], [4, 5], [7, 8], [6, 7], [2, 6], [1, 6], [4, 7],\n", - " [2, 4], [5, 8], [3, 5]]\n", + " # corners of each street\n", + " # Note: 1-based (handled below)\n", + " corner = [[1, 2], [2, 3], [4, 5], [7, 8], [6, 7], [2, 6], [1, 6], [4, 7],\n", + " [2, 4], [5, 8], [3, 5]]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(n)]\n", + " #\n", + " # declare variables\n", + " #\n", + " x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# number of telephones, to be minimized\n", - "z = solver.Sum(x)\n", + " # number of telephones, to be minimized\n", + " z = solver.Sum(x)\n", "\n", - "# ensure that all corners are covered\n", - "for i in range(num_streets):\n", - " # also, convert to 0-based\n", - " solver.Add(solver.SumGreaterOrEqual([x[j - 1] for j in corner[i]], 1))\n", + " # ensure that all corners are covered\n", + " for i in range(num_streets):\n", + " # also, convert to 0-based\n", + " solver.Add(solver.SumGreaterOrEqual([x[j - 1] for j in corner[i]], 1))\n", "\n", - "objective = solver.Minimize(z, 1)\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.AddObjective(z)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.AddObjective(z)\n", "\n", - "collector = solver.LastSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", - " [collector, objective])\n", + " collector = solver.LastSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", + " [collector, objective])\n", "\n", - "print(\"z:\", collector.ObjectiveValue(0))\n", - "print(\"x:\", [collector.Value(0, x[i]) for i in range(n)])\n", + " print(\"z:\", collector.ObjectiveValue(0))\n", + " print(\"x:\", [collector.Value(0, x[i]) for i in range(n)])\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering3.ipynb b/examples/notebook/contrib/set_covering3.ipynb index 5b89b64075..6553e8fe7b 100644 --- a/examples/notebook/contrib/set_covering3.ipynb +++ b/examples/notebook/contrib/set_covering3.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering in Google CP Solver.\n", "\n", @@ -119,78 +104,90 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set covering\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set covering\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_groups = 6\n", - "num_senators = 10\n", + " #\n", + " # data\n", + " #\n", + " num_groups = 6\n", + " num_senators = 10\n", "\n", - "# which group does a senator belong to?\n", - "belongs = [\n", - " [1, 1, 1, 1, 1, 0, 0, 0, 0, 0], # 1 southern\n", - " [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], # 2 northern\n", - " [0, 1, 1, 0, 0, 0, 0, 1, 1, 1], # 3 liberals\n", - " [1, 0, 0, 0, 1, 1, 1, 0, 0, 0], # 4 conservative\n", - " [0, 0, 1, 1, 1, 1, 1, 0, 1, 0], # 5 democrats\n", - " [1, 1, 0, 0, 0, 0, 0, 1, 0, 1] # 6 republicans\n", - "]\n", + " # which group does a senator belong to?\n", + " belongs = [\n", + " [1, 1, 1, 1, 1, 0, 0, 0, 0, 0], # 1 southern\n", + " [0, 0, 0, 0, 0, 1, 1, 1, 1, 1], # 2 northern\n", + " [0, 1, 1, 0, 0, 0, 0, 1, 1, 1], # 3 liberals\n", + " [1, 0, 0, 0, 1, 1, 1, 0, 0, 0], # 4 conservative\n", + " [0, 0, 1, 1, 1, 1, 1, 0, 1, 0], # 5 democrats\n", + " [1, 1, 0, 0, 0, 0, 0, 1, 0, 1] # 6 republicans\n", + " ]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_senators)]\n", + " #\n", + " # declare variables\n", + " #\n", + " x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_senators)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# number of assigned senators (to minimize)\n", - "z = solver.Sum(x)\n", + " # number of assigned senators (to minimize)\n", + " z = solver.Sum(x)\n", "\n", - "# ensure that each group is covered by at least\n", - "# one senator\n", - "for i in range(num_groups):\n", - " solver.Add(\n", - " solver.SumGreaterOrEqual(\n", - " [x[j] * belongs[i][j] for j in range(num_senators)], 1))\n", + " # ensure that each group is covered by at least\n", + " # one senator\n", + " for i in range(num_groups):\n", + " solver.Add(\n", + " solver.SumGreaterOrEqual(\n", + " [x[j] * belongs[i][j] for j in range(num_senators)], 1))\n", "\n", - "objective = solver.Minimize(z, 1)\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.AddObjective(z)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.AddObjective(z)\n", "\n", - "collector = solver.LastSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", - " [collector, objective])\n", + " collector = solver.LastSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", + " [collector, objective])\n", "\n", - "print(\"z:\", collector.ObjectiveValue(0))\n", - "print(\"x:\", [collector.Value(0, x[i]) for i in range(num_senators)])\n", - "for j in range(num_senators):\n", - " if collector.Value(0, x[j]) == 1:\n", - " print(\"Senator\", j + 1, \"belongs to these groups:\", end=\" \")\n", - " for i in range(num_groups):\n", - " if belongs[i][j] == 1:\n", - " print(i + 1, end=\" \")\n", - " print()\n", + " print(\"z:\", collector.ObjectiveValue(0))\n", + " print(\"x:\", [collector.Value(0, x[i]) for i in range(num_senators)])\n", + " for j in range(num_senators):\n", + " if collector.Value(0, x[j]) == 1:\n", + " print(\"Senator\", j + 1, \"belongs to these groups:\", end=\" \")\n", + " for i in range(num_groups):\n", + " if belongs[i][j] == 1:\n", + " print(i + 1, end=\" \")\n", + " print()\n", "\n", - "print()\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print()\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering4.ipynb b/examples/notebook/contrib/set_covering4.ipynb index 96ec7616ea..b13138c9b2 100644 --- a/examples/notebook/contrib/set_covering4.ipynb +++ b/examples/notebook/contrib/set_covering4.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set partition and set covering in Google CP Solver.\n", "\n", @@ -139,86 +124,102 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(set_partition=1):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set partition and set covering\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set partition and set covering\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_alternatives = 10\n", - "num_objects = 8\n", + " #\n", + " # data\n", + " #\n", + " num_alternatives = 10\n", + " num_objects = 8\n", "\n", - "# costs for the alternatives\n", - "costs = [19, 16, 18, 13, 15, 19, 15, 17, 16, 15]\n", + " # costs for the alternatives\n", + " costs = [19, 16, 18, 13, 15, 19, 15, 17, 16, 15]\n", "\n", - "# the alternatives, and their objects\n", - "a = [\n", - " # 1 2 3 4 5 6 7 8 the objects\n", - " [1, 0, 0, 0, 0, 1, 0, 0], # alternative 1\n", - " [0, 1, 0, 0, 0, 1, 0, 1], # alternative 2\n", - " [1, 0, 0, 1, 0, 0, 1, 0], # alternative 3\n", - " [0, 1, 1, 0, 1, 0, 0, 0], # alternative 4\n", - " [0, 1, 0, 0, 1, 0, 0, 0], # alternative 5\n", - " [0, 1, 1, 0, 0, 0, 0, 0], # alternative 6\n", - " [0, 1, 1, 1, 0, 0, 0, 0], # alternative 7\n", - " [0, 0, 0, 1, 1, 0, 0, 1], # alternative 8\n", - " [0, 0, 1, 0, 0, 1, 0, 1], # alternative 9\n", - " [1, 0, 0, 0, 0, 1, 1, 0] # alternative 10\n", - "]\n", + " # the alternatives, and their objects\n", + " a = [\n", + " # 1 2 3 4 5 6 7 8 the objects\n", + " [1, 0, 0, 0, 0, 1, 0, 0], # alternative 1\n", + " [0, 1, 0, 0, 0, 1, 0, 1], # alternative 2\n", + " [1, 0, 0, 1, 0, 0, 1, 0], # alternative 3\n", + " [0, 1, 1, 0, 1, 0, 0, 0], # alternative 4\n", + " [0, 1, 0, 0, 1, 0, 0, 0], # alternative 5\n", + " [0, 1, 1, 0, 0, 0, 0, 0], # alternative 6\n", + " [0, 1, 1, 1, 0, 0, 0, 0], # alternative 7\n", + " [0, 0, 0, 1, 1, 0, 0, 1], # alternative 8\n", + " [0, 0, 1, 0, 0, 1, 0, 1], # alternative 9\n", + " [1, 0, 0, 0, 0, 1, 1, 0] # alternative 10\n", + " ]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_alternatives)]\n", + " #\n", + " # declare variables\n", + " #\n", + " x = [solver.IntVar(0, 1, \"x[%i]\" % i) for i in range(num_alternatives)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# sum the cost of the choosen alternative,\n", - "# to be minimized\n", - "z = solver.ScalProd(x, costs)\n", + " # sum the cost of the choosen alternative,\n", + " # to be minimized\n", + " z = solver.ScalProd(x, costs)\n", "\n", - "#\n", - "for j in range(num_objects):\n", - " if set_partition == 1:\n", - " solver.Add(\n", - " solver.SumEquality([x[i] * a[i][j] for i in range(num_alternatives)],\n", - " 1))\n", - " else:\n", - " solver.Add(\n", - " solver.SumGreaterOrEqual(\n", - " [x[i] * a[i][j] for i in range(num_alternatives)], 1))\n", + " #\n", + " for j in range(num_objects):\n", + " if set_partition == 1:\n", + " solver.Add(\n", + " solver.SumEquality([x[i] * a[i][j] for i in range(num_alternatives)],\n", + " 1))\n", + " else:\n", + " solver.Add(\n", + " solver.SumGreaterOrEqual(\n", + " [x[i] * a[i][j] for i in range(num_alternatives)], 1))\n", "\n", - "objective = solver.Minimize(z, 1)\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.AddObjective(z)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.AddObjective(z)\n", "\n", - "collector = solver.LastSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase([x[i] for i in range(num_alternatives)],\n", - " solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", - " [collector, objective])\n", + " collector = solver.LastSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase([x[i] for i in range(num_alternatives)],\n", + " solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", + " [collector, objective])\n", "\n", - "print(\"z:\", collector.ObjectiveValue(0))\n", - "print(\n", - " \"selected alternatives:\",\n", - " [i + 1 for i in range(num_alternatives) if collector.Value(0, x[i]) == 1])\n", + " print(\"z:\", collector.ObjectiveValue(0))\n", + " print(\n", + " \"selected alternatives:\",\n", + " [i + 1 for i in range(num_alternatives) if collector.Value(0, x[i]) == 1])\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "print(\"Set partition:\")\n", + "main(1)\n", + "\n", + "print(\"\\nSet covering:\")\n", + "main(0)\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering_deployment.ipynb b/examples/notebook/contrib/set_covering_deployment.ipynb index b0cf8f08ff..615ad39c9f 100644 --- a/examples/notebook/contrib/set_covering_deployment.ipynb +++ b/examples/notebook/contrib/set_covering_deployment.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering deployment in Google CP Solver\n", "\n", @@ -112,94 +97,106 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set covering deployment\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set covering deployment\")\n", "\n", - "#\n", - "# data\n", - "#\n", + " #\n", + " # data\n", + " #\n", "\n", - "countries = [\n", - " \"Alexandria\", \"Asia Minor\", \"Britain\", \"Byzantium\", \"Gaul\", \"Iberia\",\n", - " \"Rome\", \"Tunis\"\n", - "]\n", - "n = len(countries)\n", + " countries = [\n", + " \"Alexandria\", \"Asia Minor\", \"Britain\", \"Byzantium\", \"Gaul\", \"Iberia\",\n", + " \"Rome\", \"Tunis\"\n", + " ]\n", + " n = len(countries)\n", "\n", - "# the incidence matrix (neighbours)\n", - "mat = [[0, 1, 0, 1, 0, 0, 1, 1], [1, 0, 0, 1, 0, 0, 0, 0],\n", - " [0, 0, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 0, 0, 1, 0],\n", - " [0, 0, 1, 0, 0, 1, 1, 0], [0, 0, 1, 0, 1, 0, 1, 1],\n", - " [1, 0, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 1, 1, 0]]\n", + " # the incidence matrix (neighbours)\n", + " mat = [[0, 1, 0, 1, 0, 0, 1, 1], [1, 0, 0, 1, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 0, 0, 1, 0],\n", + " [0, 0, 1, 0, 0, 1, 1, 0], [0, 0, 1, 0, 1, 0, 1, 1],\n", + " [1, 0, 0, 1, 1, 1, 0, 1], [1, 0, 0, 0, 0, 1, 1, 0]]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", + " #\n", + " # declare variables\n", + " #\n", "\n", - "# First army\n", - "X = [solver.IntVar(0, 1, \"X[%i]\" % i) for i in range(n)]\n", + " # First army\n", + " X = [solver.IntVar(0, 1, \"X[%i]\" % i) for i in range(n)]\n", "\n", - "# Second (reserv) army\n", - "Y = [solver.IntVar(0, 1, \"Y[%i]\" % i) for i in range(n)]\n", + " # Second (reserv) army\n", + " Y = [solver.IntVar(0, 1, \"Y[%i]\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# total number of armies\n", - "num_armies = solver.Sum([X[i] + Y[i] for i in range(n)])\n", + " # total number of armies\n", + " num_armies = solver.Sum([X[i] + Y[i] for i in range(n)])\n", "\n", - "#\n", - "# Constraint 1: There is always an army in a city\n", - "# (+ maybe a backup)\n", - "# Or rather: Is there a backup, there\n", - "# must be an an army\n", - "#\n", - "[solver.Add(X[i] >= Y[i]) for i in range(n)]\n", + " #\n", + " # Constraint 1: There is always an army in a city\n", + " # (+ maybe a backup)\n", + " # Or rather: Is there a backup, there\n", + " # must be an an army\n", + " #\n", + " [solver.Add(X[i] >= Y[i]) for i in range(n)]\n", "\n", - "#\n", - "# Constraint 2: There should always be an backup army near every city\n", - "#\n", - "for i in range(n):\n", - " neighbors = solver.Sum([Y[j] for j in range(n) if mat[i][j] == 1])\n", - " solver.Add(X[i] + neighbors >= 1)\n", + " #\n", + " # Constraint 2: There should always be an backup army near every city\n", + " #\n", + " for i in range(n):\n", + " neighbors = solver.Sum([Y[j] for j in range(n) if mat[i][j] == 1])\n", + " solver.Add(X[i] + neighbors >= 1)\n", "\n", - "objective = solver.Minimize(num_armies, 1)\n", + " objective = solver.Minimize(num_armies, 1)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(X)\n", - "solution.Add(Y)\n", - "solution.Add(num_armies)\n", - "solution.AddObjective(num_armies)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(X)\n", + " solution.Add(Y)\n", + " solution.Add(num_armies)\n", + " solution.AddObjective(num_armies)\n", "\n", - "collector = solver.LastSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase(X + Y, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", - " [collector, objective])\n", + " collector = solver.LastSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase(X + Y, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT),\n", + " [collector, objective])\n", "\n", - "print(\"num_armies:\", collector.ObjectiveValue(0))\n", - "print(\"X:\", [collector.Value(0, X[i]) for i in range(n)])\n", - "print(\"Y:\", [collector.Value(0, Y[i]) for i in range(n)])\n", + " print(\"num_armies:\", collector.ObjectiveValue(0))\n", + " print(\"X:\", [collector.Value(0, X[i]) for i in range(n)])\n", + " print(\"Y:\", [collector.Value(0, Y[i]) for i in range(n)])\n", "\n", - "for i in range(n):\n", - " if collector.Value(0, X[i]) == 1:\n", - " print(\"army:\", countries[i], end=\" \")\n", - " if collector.Value(0, Y[i]) == 1:\n", - " print(\"reserv army:\", countries[i], \" \")\n", - "print()\n", + " for i in range(n):\n", + " if collector.Value(0, X[i]) == 1:\n", + " print(\"army:\", countries[i], end=\" \")\n", + " if collector.Value(0, Y[i]) == 1:\n", + " print(\"reserv army:\", countries[i], \" \")\n", + " print()\n", "\n", - "print()\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print()\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/set_covering_skiena.ipynb b/examples/notebook/contrib/set_covering_skiena.ipynb index a26ae65143..36d35c7e2d 100644 --- a/examples/notebook/contrib/set_covering_skiena.ipynb +++ b/examples/notebook/contrib/set_covering_skiena.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set covering in Google CP Solver.\n", "\n", @@ -112,81 +97,93 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Set covering Skiena')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Set covering Skiena')\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_sets = 7\n", - "num_elements = 12\n", - "belongs = [\n", - " # 1 2 3 4 5 6 7 8 9 0 1 2 elements\n", - " [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # Set 1\n", - " [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], # 2\n", - " [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], # 3\n", - " [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0], # 4\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], # 5\n", - " [1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0], # 6\n", - " [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1] # 7\n", - "]\n", + " #\n", + " # data\n", + " #\n", + " num_sets = 7\n", + " num_elements = 12\n", + " belongs = [\n", + " # 1 2 3 4 5 6 7 8 9 0 1 2 elements\n", + " [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], # Set 1\n", + " [0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0], # 2\n", + " [0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0], # 3\n", + " [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0], # 4\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], # 5\n", + " [1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0], # 6\n", + " [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1] # 7\n", + " ]\n", "\n", - "#\n", - "# variables\n", - "#\n", - "x = [solver.IntVar(0, 1, 'x[%i]' % i) for i in range(num_sets)]\n", + " #\n", + " # variables\n", + " #\n", + " x = [solver.IntVar(0, 1, 'x[%i]' % i) for i in range(num_sets)]\n", "\n", - "# number of choosen sets\n", - "z = solver.IntVar(0, num_sets * 2, 'z')\n", + " # number of choosen sets\n", + " z = solver.IntVar(0, num_sets * 2, 'z')\n", "\n", - "# total number of elements in the choosen sets\n", - "tot_elements = solver.IntVar(0, num_sets * num_elements)\n", + " # total number of elements in the choosen sets\n", + " tot_elements = solver.IntVar(0, num_sets * num_elements)\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(z == solver.Sum(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(z == solver.Sum(x))\n", "\n", - "# all sets must be used\n", - "for j in range(num_elements):\n", - " s = solver.Sum([belongs[i][j] * x[i] for i in range(num_sets)])\n", - " solver.Add(s >= 1)\n", + " # all sets must be used\n", + " for j in range(num_elements):\n", + " s = solver.Sum([belongs[i][j] * x[i] for i in range(num_sets)])\n", + " solver.Add(s >= 1)\n", "\n", - "# number of used elements\n", - "solver.Add(tot_elements == solver.Sum([\n", - " x[i] * belongs[i][j] for i in range(num_sets) for j in range(num_elements)\n", - "]))\n", + " # number of used elements\n", + " solver.Add(tot_elements == solver.Sum([\n", + " x[i] * belongs[i][j] for i in range(num_sets) for j in range(num_elements)\n", + " ]))\n", "\n", - "# objective\n", - "objective = solver.Minimize(z, 1)\n", + " # objective\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db, [objective])\n", + " solver.NewSearch(db, [objective])\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('z:', z.Value())\n", - " print('tot_elements:', tot_elements.Value())\n", - " print('x:', [x[i].Value() for i in range(num_sets)])\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('z:', z.Value())\n", + " print('tot_elements:', tot_elements.Value())\n", + " print('x:', [x[i].Value() for i in range(num_sets)])\n", "\n", - "solver.EndSearch()\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", + " 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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/set_partition.ipynb b/examples/notebook/contrib/set_partition.ipynb index e42e954dfb..e3d9c225c5 100644 --- a/examples/notebook/contrib/set_partition.ipynb +++ b/examples/notebook/contrib/set_partition.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Set partition problem in Google CP Solver.\n", "\n", @@ -118,8 +103,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -143,101 +136,110 @@ " solver.Add(solver.Sum(b) == n)\n", "\n", "\n", + "def main(n=16, num_sets=2):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Set partition\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Set partition\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"n:\", n)\n", - "print(\"num_sets:\", num_sets)\n", - "print()\n", + " #\n", + " # data\n", + " #\n", + " print(\"n:\", n)\n", + " print(\"num_sets:\", num_sets)\n", + " print()\n", "\n", - "# Check sizes\n", - "assert n % num_sets == 0, \"Equal sets is not possible.\"\n", + " # Check sizes\n", + " assert n % num_sets == 0, \"Equal sets is not possible.\"\n", "\n", - "#\n", - "# variables\n", - "#\n", + " #\n", + " # variables\n", + " #\n", "\n", - "# the set\n", - "a = {}\n", - "for i in range(num_sets):\n", - " for j in range(n):\n", - " a[i, j] = solver.IntVar(0, 1, \"a[%i,%i]\" % (i, j))\n", - "\n", - "a_flat = [a[i, j] for i in range(num_sets) for j in range(n)]\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "\n", - "# partition set\n", - "partition_sets(a, num_sets, n)\n", - "\n", - "for i in range(num_sets):\n", - " for j in range(i, num_sets):\n", - "\n", - " # same cardinality\n", - " solver.Add(\n", - " solver.Sum([a[i, k] for k in range(n)]) == solver.Sum(\n", - " [a[j, k] for k in range(n)]))\n", - "\n", - " # same sum\n", - " solver.Add(\n", - " solver.Sum([k * a[i, k] for k in range(n)]) == solver.Sum(\n", - " [k * a[j, k] for k in range(n)]))\n", - "\n", - " # same sum squared\n", - " solver.Add(\n", - " solver.Sum([(k * a[i, k]) * (k * a[i, k]) for k in range(n)]) ==\n", - " solver.Sum([(k * a[j, k]) * (k * a[j, k]) for k in range(n)]))\n", - "\n", - "# symmetry breaking for num_sets == 2\n", - "if num_sets == 2:\n", - " solver.Add(a[0, 0] == 1)\n", - "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(a_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", - "\n", - "solver.NewSearch(db)\n", - "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " a_val = {}\n", + " # the set\n", + " a = {}\n", " for i in range(num_sets):\n", " for j in range(n):\n", - " a_val[i, j] = a[i, j].Value()\n", + " a[i, j] = solver.IntVar(0, 1, \"a[%i,%i]\" % (i, j))\n", "\n", - " sq = sum([(j + 1) * a_val[0, j] for j in range(n)])\n", - " print(\"sums:\", sq)\n", - " sq2 = sum([((j + 1) * a_val[0, j])**2 for j in range(n)])\n", - " print(\"sums squared:\", sq2)\n", + " a_flat = [a[i, j] for i in range(num_sets) for j in range(n)]\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + "\n", + " # partition set\n", + " partition_sets(a, num_sets, n)\n", "\n", " for i in range(num_sets):\n", - " if sum([a_val[i, j] for j in range(n)]):\n", - " print(i + 1, \":\", end=\" \")\n", + " for j in range(i, num_sets):\n", + "\n", + " # same cardinality\n", + " solver.Add(\n", + " solver.Sum([a[i, k] for k in range(n)]) == solver.Sum(\n", + " [a[j, k] for k in range(n)]))\n", + "\n", + " # same sum\n", + " solver.Add(\n", + " solver.Sum([k * a[i, k] for k in range(n)]) == solver.Sum(\n", + " [k * a[j, k] for k in range(n)]))\n", + "\n", + " # same sum squared\n", + " solver.Add(\n", + " solver.Sum([(k * a[i, k]) * (k * a[i, k]) for k in range(n)]) ==\n", + " solver.Sum([(k * a[j, k]) * (k * a[j, k]) for k in range(n)]))\n", + "\n", + " # symmetry breaking for num_sets == 2\n", + " if num_sets == 2:\n", + " solver.Add(a[0, 0] == 1)\n", + "\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(a_flat, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + "\n", + " solver.NewSearch(db)\n", + "\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " a_val = {}\n", + " for i in range(num_sets):\n", " for j in range(n):\n", - " if a_val[i, j] == 1:\n", - " print(j + 1, end=\" \")\n", - " print()\n", + " a_val[i, j] = a[i, j].Value()\n", + "\n", + " sq = sum([(j + 1) * a_val[0, j] for j in range(n)])\n", + " print(\"sums:\", sq)\n", + " sq2 = sum([((j + 1) * a_val[0, j])**2 for j in range(n)])\n", + " print(\"sums squared:\", sq2)\n", + "\n", + " for i in range(num_sets):\n", + " if sum([a_val[i, j] for j in range(n)]):\n", + " print(i + 1, \":\", end=\" \")\n", + " for j in range(n):\n", + " if a_val[i, j] == 1:\n", + " print(j + 1, end=\" \")\n", + " print()\n", + "\n", + " print()\n", + " num_solutions += 1\n", + "\n", + " solver.EndSearch()\n", "\n", " print()\n", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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 = 16\n", - "num_sets = 2\n" + "num_sets = 2\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", + "if len(sys.argv) > 2:\n", + " num_sets = int(sys.argv[2])\n", + "\n", + "main(n, num_sets)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/sicherman_dice.ipynb b/examples/notebook/contrib/sicherman_dice.ipynb index 44c49debc1..a9790f6587 100644 --- a/examples/notebook/contrib/sicherman_dice.ipynb +++ b/examples/notebook/contrib/sicherman_dice.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Sicherman Dice in Google CP Solver.\n", "\n", @@ -132,81 +117,93 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Sicherman dice\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Sicherman dice\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 6\n", - "m = 10\n", + " #\n", + " # data\n", + " #\n", + " n = 6\n", + " m = 10\n", "\n", - "# standard distribution\n", - "standard_dist = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]\n", + " # standard distribution\n", + " standard_dist = [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]\n", "\n", - "#\n", - "# declare variables\n", - "#\n", + " #\n", + " # declare variables\n", + " #\n", "\n", - "# the two dice\n", - "x1 = [solver.IntVar(0, m, \"x1(%i)\" % i) for i in range(n)]\n", - "x2 = [solver.IntVar(0, m, \"x2(%i)\" % i) for i in range(n)]\n", + " # the two dice\n", + " x1 = [solver.IntVar(0, m, \"x1(%i)\" % i) for i in range(n)]\n", + " x2 = [solver.IntVar(0, m, \"x2(%i)\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "# [solver.Add(standard_dist[k] == solver.Sum([x1[i] + x2[j] == k+2 for i in range(n) for j in range(n)]))\n", - "# for k in range(len(standard_dist))]\n", - "for k in range(len(standard_dist)):\n", - " tmp = [solver.BoolVar() for i in range(n) for j in range(n)]\n", - " for i in range(n):\n", - " for j in range(n):\n", - " solver.Add(tmp[i * n + j] == solver.IsEqualCstVar(x1[i] + x2[j], k + 2))\n", - " solver.Add(standard_dist[k] == solver.Sum(tmp))\n", + " #\n", + " # constraints\n", + " #\n", + " # [solver.Add(standard_dist[k] == solver.Sum([x1[i] + x2[j] == k+2 for i in range(n) for j in range(n)]))\n", + " # for k in range(len(standard_dist))]\n", + " for k in range(len(standard_dist)):\n", + " tmp = [solver.BoolVar() for i in range(n) for j in range(n)]\n", + " for i in range(n):\n", + " for j in range(n):\n", + " solver.Add(tmp[i * n + j] == solver.IsEqualCstVar(x1[i] + x2[j], k + 2))\n", + " solver.Add(standard_dist[k] == solver.Sum(tmp))\n", "\n", - "# symmetry breaking\n", - "[solver.Add(x1[i] <= x1[i + 1]) for i in range(n - 1)],\n", - "[solver.Add(x2[i] <= x2[i + 1]) for i in range(n - 1)],\n", - "[solver.Add(x1[i] <= x2[i]) for i in range(n - 1)],\n", + " # symmetry breaking\n", + " [solver.Add(x1[i] <= x1[i + 1]) for i in range(n - 1)],\n", + " [solver.Add(x2[i] <= x2[i + 1]) for i in range(n - 1)],\n", + " [solver.Add(x1[i] <= x2[i]) for i in range(n - 1)],\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x1)\n", - "solution.Add(x2)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x1)\n", + " solution.Add(x2)\n", "\n", - "# db: DecisionBuilder\n", - "db = solver.Phase(x1 + x2, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n", + " # db: DecisionBuilder\n", + " db = solver.Phase(x1 + x2, solver.INT_VAR_SIMPLE, solver.ASSIGN_MIN_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print(\"x1:\", [x1[i].Value() for i in range(n)])\n", + " print(\"x2:\", [x2[i].Value() for i in range(n)])\n", + " print()\n", + "\n", + " num_solutions += 1\n", + " solver.EndSearch()\n", "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print(\"x1:\", [x1[i].Value() for i in range(n)])\n", - " print(\"x2:\", [x2[i].Value() for i in range(n)])\n", " print()\n", + " print(\"num_solutions:\", num_solutions, \"solver.solutions:\",\n", + " solver.Solutions())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + " print(\"MemoryUsage:\", solver.MemoryUsage())\n", + " print(\"SearchDepth:\", solver.SearchDepth())\n", + " print(\"SolveDepth:\", solver.SolveDepth())\n", + " print(\"stamp:\", solver.Stamp())\n", + " print(\"solver\", solver)\n", "\n", - " num_solutions += 1\n", - "solver.EndSearch()\n", "\n", - "print()\n", - "print(\"num_solutions:\", num_solutions, \"solver.solutions:\",\n", - " solver.Solutions())\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", - "print(\"MemoryUsage:\", solver.MemoryUsage())\n", - "print(\"SearchDepth:\", solver.SearchDepth())\n", - "print(\"SolveDepth:\", solver.SolveDepth())\n", - "print(\"stamp:\", solver.Stamp())\n", - "print(\"solver\", solver)\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/ski_assignment.ipynb b/examples/notebook/contrib/ski_assignment.ipynb index c55a654e6d..e7b1c1bc11 100644 --- a/examples/notebook/contrib/ski_assignment.ipynb +++ b/examples/notebook/contrib/ski_assignment.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Ski assignment in Google CP Solver.\n", "\n", @@ -121,73 +106,85 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Ski assignment')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Ski assignment')\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_skis = 6\n", - "num_skiers = 5\n", - "ski_heights = [1, 2, 5, 7, 13, 21]\n", - "skier_heights = [3, 4, 7, 11, 18]\n", + " #\n", + " # data\n", + " #\n", + " num_skis = 6\n", + " num_skiers = 5\n", + " ski_heights = [1, 2, 5, 7, 13, 21]\n", + " skier_heights = [3, 4, 7, 11, 18]\n", "\n", - "#\n", - "# variables\n", - "#\n", + " #\n", + " # variables\n", + " #\n", "\n", - "# which ski to choose for each skier\n", - "x = [solver.IntVar(0, num_skis - 1, 'x[%i]' % i) for i in range(num_skiers)]\n", - "z = solver.IntVar(0, sum(ski_heights), 'z')\n", + " # which ski to choose for each skier\n", + " x = [solver.IntVar(0, num_skis - 1, 'x[%i]' % i) for i in range(num_skiers)]\n", + " z = solver.IntVar(0, sum(ski_heights), 'z')\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(solver.AllDifferent(x))\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(solver.AllDifferent(x))\n", "\n", - "z_tmp = [\n", - " abs(solver.Element(ski_heights, x[i]) - skier_heights[i])\n", - " for i in range(num_skiers)\n", - "]\n", - "solver.Add(z == sum(z_tmp))\n", + " z_tmp = [\n", + " abs(solver.Element(ski_heights, x[i]) - skier_heights[i])\n", + " for i in range(num_skiers)\n", + " ]\n", + " solver.Add(z == sum(z_tmp))\n", "\n", - "# objective\n", - "objective = solver.Minimize(z, 1)\n", + " # objective\n", + " objective = solver.Minimize(z, 1)\n", "\n", - "#\n", - "# search and result\n", - "#\n", - "db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + " #\n", + " # search and result\n", + " #\n", + " db = solver.Phase(x, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", "\n", - "solver.NewSearch(db, [objective])\n", + " solver.NewSearch(db, [objective])\n", + "\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " num_solutions += 1\n", + " print('total differences:', z.Value())\n", + " for i in range(num_skiers):\n", + " x_val = x[i].Value()\n", + " ski_height = ski_heights[x[i].Value()]\n", + " diff = ski_height - skier_heights[i]\n", + " print('Skier %i: Ski %i with length %2i (diff: %2i)' %\\\n", + " (i, x_val, ski_height, diff))\n", + " print()\n", + "\n", + " solver.EndSearch()\n", "\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " num_solutions += 1\n", - " print('total differences:', z.Value())\n", - " for i in range(num_skiers):\n", - " x_val = x[i].Value()\n", - " ski_height = ski_heights[x[i].Value()]\n", - " diff = ski_height - skier_heights[i]\n", - " print('Skier %i: Ski %i with length %2i (diff: %2i)' %\\\n", - " (i, x_val, ski_height, diff))\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", - "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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/slitherlink.ipynb b/examples/notebook/contrib/slitherlink.ipynb index 0c3bb2a882..6ce05565e6 100644 --- a/examples/notebook/contrib/slitherlink.ipynb +++ b/examples/notebook/contrib/slitherlink.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -357,6 +357,10 @@ " PrintSolution(data, h_arcs, v_arcs)\n", " solver.EndSearch()\n", "\n", + "\n", + "SlitherLink(small)\n", + "SlitherLink(medium)\n", + "SlitherLink(big)\n", "\n" ] } diff --git a/examples/notebook/contrib/sports_schedule_sat.ipynb b/examples/notebook/contrib/sports_schedule_sat.ipynb index 6fa359232d..cfe365535f 100644 --- a/examples/notebook/contrib/sports_schedule_sat.ipynb +++ b/examples/notebook/contrib/sports_schedule_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,28 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "# Based on sports_scheduling_sat.cc, Copyright 2010-2021 Google LLC\n", - "#\n", - "# Translated to Python by James E. Marca August 2019\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", - "\"\"\"Sports scheduling problem.\n", + "Sports scheduling problem.\n", "\n", "We want to solve the problem of scheduling of team matches in a\n", "double round robin tournament. Given a number of teams, we want\n", @@ -123,8 +106,16 @@ "\n", "For a version with pool constraints, plus tests, etc, see\n", "https://github.com/jmarca/sports_scheduling\n", - "\n", - "\"\"\"\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import argparse\n", "import os\n", "import re\n", @@ -538,105 +529,109 @@ " # print(' %s is %i' % (b.Name(), solver.Value(b)))\n", "\n", "\n", - "\"\"\"Entry point of the program.\"\"\"\n", - "parser = argparse.ArgumentParser(\n", - " description='Solve sports league match play assignment problem')\n", - "parser.add_argument('-t,--teams',\n", - " type=int,\n", - " dest='num_teams',\n", - " default=10,\n", - " help='Number of teams in the league')\n", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " parser = argparse.ArgumentParser(\n", + " description='Solve sports league match play assignment problem')\n", + " parser.add_argument('-t,--teams',\n", + " type=int,\n", + " dest='num_teams',\n", + " default=10,\n", + " help='Number of teams in the league')\n", "\n", - "parser.add_argument(\n", - " '-d,--days',\n", - " type=int,\n", - " dest='num_matchdays',\n", - " default=2 * 10 - 2,\n", - " help=\n", - " 'Number of days on which matches are played. Default is enough days such that every team can play every other team, or (number of teams - 1)'\n", - ")\n", + " parser.add_argument(\n", + " '-d,--days',\n", + " type=int,\n", + " dest='num_matchdays',\n", + " default=2 * 10 - 2,\n", + " help=\n", + " 'Number of days on which matches are played. Default is enough days such that every team can play every other team, or (number of teams - 1)'\n", + " )\n", "\n", - "parser.add_argument(\n", - " '--matches_per_day',\n", - " type=int,\n", - " dest='num_matches_per_day',\n", - " default=10 - 1,\n", - " help=\n", - " 'Number of matches played per day. Default is number of teams divided by 2. If greater than the number of teams, then this implies some teams will play each other more than once. In that case, home and away should alternate between the teams in repeated matchups.'\n", - ")\n", + " parser.add_argument(\n", + " '--matches_per_day',\n", + " type=int,\n", + " dest='num_matches_per_day',\n", + " default=10 - 1,\n", + " help=\n", + " 'Number of matches played per day. Default is number of teams divided by 2. If greater than the number of teams, then this implies some teams will play each other more than once. In that case, home and away should alternate between the teams in repeated matchups.'\n", + " )\n", "\n", - "parser.add_argument(\n", - " '--csv',\n", - " type=str,\n", - " dest='csv',\n", - " default='output.csv',\n", - " help='A file to dump the team assignments. Default is output.csv')\n", + " parser.add_argument(\n", + " '--csv',\n", + " type=str,\n", + " dest='csv',\n", + " default='output.csv',\n", + " help='A file to dump the team assignments. Default is output.csv')\n", "\n", - "parser.add_argument(\n", - " '--timelimit',\n", - " type=int,\n", - " dest='time_limit',\n", - " default=60,\n", - " help='Maximum run time for solver, in seconds. Default is 60 seconds.')\n", + " parser.add_argument(\n", + " '--timelimit',\n", + " type=int,\n", + " dest='time_limit',\n", + " default=60,\n", + " help='Maximum run time for solver, in seconds. Default is 60 seconds.')\n", "\n", - "parser.add_argument(\n", - " '--cpu',\n", - " type=int,\n", - " dest='cpu',\n", - " help=\n", - " 'Number of workers (CPUs) to use for solver. Default is 6 or number of CPUs available, whichever is lower'\n", - ")\n", + " parser.add_argument(\n", + " '--cpu',\n", + " type=int,\n", + " dest='cpu',\n", + " help=\n", + " 'Number of workers (CPUs) to use for solver. Default is 6 or number of CPUs available, whichever is lower'\n", + " )\n", "\n", - "parser.add_argument('--debug',\n", - " action='store_true',\n", - " help=\"Turn on some print statements.\")\n", + " parser.add_argument('--debug',\n", + " action='store_true',\n", + " help=\"Turn on some print statements.\")\n", "\n", - "parser.add_argument(\n", - " '--max_home_stand',\n", - " type=int,\n", - " dest='max_home_stand',\n", - " default=2,\n", - " help=\n", - " \"Maximum consecutive home or away games. Default to 2, which means three home or away games in a row is forbidden.\"\n", - ")\n", + " parser.add_argument(\n", + " '--max_home_stand',\n", + " type=int,\n", + " dest='max_home_stand',\n", + " default=2,\n", + " help=\n", + " \"Maximum consecutive home or away games. Default to 2, which means three home or away games in a row is forbidden.\"\n", + " )\n", "\n", - "args = parser.parse_args()\n", + " args = parser.parse_args()\n", "\n", - "# set default for num_matchdays\n", - "num_matches_per_day = args.num_matches_per_day\n", - "if not num_matches_per_day:\n", - " num_matches_per_day = args.num_teams // 2\n", - "ncpu = 8\n", - "try:\n", - " ncpu = len(os.sched_getaffinity(0))\n", - "except AttributeError:\n", - " pass\n", - "cpu = args.cpu\n", - "if not cpu:\n", - " cpu = min(6, ncpu)\n", - " print('Setting number of search workers to %i' % cpu)\n", + " # set default for num_matchdays\n", + " num_matches_per_day = args.num_matches_per_day\n", + " if not num_matches_per_day:\n", + " num_matches_per_day = args.num_teams // 2\n", + " ncpu = 8\n", + " try:\n", + " ncpu = len(os.sched_getaffinity(0))\n", + " except AttributeError:\n", + " pass\n", + " cpu = args.cpu\n", + " if not cpu:\n", + " cpu = min(6, ncpu)\n", + " print('Setting number of search workers to %i' % cpu)\n", "\n", - "if cpu > ncpu:\n", - " print(\n", - " 'You asked for %i workers to be used, but the os only reports %i CPUs available. This might slow down processing'\n", - " % (cpu, ncpu))\n", - "\n", - "if cpu != 6:\n", - " # don't whinge at user if cpu is set to 6\n", - " if cpu < ncpu:\n", + " if cpu > ncpu:\n", " print(\n", - " 'Using %i workers, but there are %i CPUs available. You might get faster results by using the command line option --cpu %i, but be aware ORTools CP-SAT solver is tuned to 6 CPUs'\n", - " % (cpu, ncpu, ncpu))\n", + " 'You asked for %i workers to be used, but the os only reports %i CPUs available. This might slow down processing'\n", + " % (cpu, ncpu))\n", "\n", - " if cpu > 6:\n", - " print(\n", - " 'Using %i workers. Be aware ORTools CP-SAT solver is tuned to 6 CPUs'\n", - " % cpu)\n", + " if cpu != 6:\n", + " # don't whinge at user if cpu is set to 6\n", + " if cpu < ncpu:\n", + " print(\n", + " 'Using %i workers, but there are %i CPUs available. You might get faster results by using the command line option --cpu %i, but be aware ORTools CP-SAT solver is tuned to 6 CPUs'\n", + " % (cpu, ncpu, ncpu))\n", "\n", - "# assign_matches()\n", - "assign_matches(args.num_teams, args.num_matchdays, num_matches_per_day,\n", - " args.max_home_stand, args.time_limit, cpu, args.csv,\n", - " args.debug)\n", + " if cpu > 6:\n", + " print(\n", + " 'Using %i workers. Be aware ORTools CP-SAT solver is tuned to 6 CPUs'\n", + " % cpu)\n", + "\n", + " # assign_matches()\n", + " assign_matches(args.num_teams, args.num_matchdays, num_matches_per_day,\n", + " args.max_home_stand, args.time_limit, cpu, args.csv,\n", + " args.debug)\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/stable_marriage.ipynb b/examples/notebook/contrib/stable_marriage.ipynb index aea0682848..712711b848 100644 --- a/examples/notebook/contrib/stable_marriage.ipynb +++ b/examples/notebook/contrib/stable_marriage.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Stable marriage problem in Google CP Solver.\n", "\n", @@ -111,104 +96,114 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(ranks, problem_name):\n", "\n", - "# Create the solver\n", - "solver = pywrapcp.Solver(\"Stable marriage\")\n", + " # Create the solver\n", + " solver = pywrapcp.Solver(\"Stable marriage\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"Problem name:\", problem_name)\n", + " #\n", + " # data\n", + " #\n", + " print(\"Problem name:\", problem_name)\n", "\n", - "rankMen = ranks[\"rankMen\"]\n", - "rankWomen = ranks[\"rankWomen\"]\n", + " rankMen = ranks[\"rankMen\"]\n", + " rankWomen = ranks[\"rankWomen\"]\n", "\n", - "n = len(rankMen)\n", + " n = len(rankMen)\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "wife = [solver.IntVar(0, n - 1, \"wife[%i]\" % i) for i in range(n)]\n", - "husband = [solver.IntVar(0, n - 1, \"husband[%i]\" % i) for i in range(n)]\n", + " #\n", + " # declare variables\n", + " #\n", + " wife = [solver.IntVar(0, n - 1, \"wife[%i]\" % i) for i in range(n)]\n", + " husband = [solver.IntVar(0, n - 1, \"husband[%i]\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# forall(m in Men)\n", - "# cp.post(husband[wife[m]] == m);\n", - "for m in range(n):\n", - " solver.Add(solver.Element(husband, wife[m]) == m)\n", + " # forall(m in Men)\n", + " # cp.post(husband[wife[m]] == m);\n", + " for m in range(n):\n", + " solver.Add(solver.Element(husband, wife[m]) == m)\n", "\n", - "# forall(w in Women)\n", - "# cp.post(wife[husband[w]] == w);\n", - "for w in range(n):\n", - " solver.Add(solver.Element(wife, husband[w]) == w)\n", + " # forall(w in Women)\n", + " # cp.post(wife[husband[w]] == w);\n", + " for w in range(n):\n", + " solver.Add(solver.Element(wife, husband[w]) == w)\n", "\n", - "# forall(m in Men, o in Women)\n", - "# cp.post(rankMen[m,o] < rankMen[m, wife[m]] => rankWomen[o,husband[o]] <\n", - "# rankWomen[o,m]);\n", - "for m in range(n):\n", - " for o in range(n):\n", - " b1 = solver.IsGreaterCstVar(\n", - " solver.Element(rankMen[m], wife[m]), rankMen[m][o])\n", - " b2 = (\n", - " solver.IsLessCstVar(\n", - " solver.Element(rankWomen[o], husband[o]), rankWomen[o][m]))\n", - " solver.Add(b1 - b2 <= 0)\n", + " # forall(m in Men, o in Women)\n", + " # cp.post(rankMen[m,o] < rankMen[m, wife[m]] => rankWomen[o,husband[o]] <\n", + " # rankWomen[o,m]);\n", + " for m in range(n):\n", + " for o in range(n):\n", + " b1 = solver.IsGreaterCstVar(\n", + " solver.Element(rankMen[m], wife[m]), rankMen[m][o])\n", + " b2 = (\n", + " solver.IsLessCstVar(\n", + " solver.Element(rankWomen[o], husband[o]), rankWomen[o][m]))\n", + " solver.Add(b1 - b2 <= 0)\n", "\n", - "# forall(w in Women, o in Men)\n", - "# cp.post(rankWomen[w,o] < rankWomen[w,husband[w]] => rankMen[o,wife[o]] <\n", - "# rankMen[o,w]);\n", - "for w in range(n):\n", - " for o in range(n):\n", - " b1 = solver.IsGreaterCstVar(\n", - " solver.Element(rankWomen[w], husband[w]), rankWomen[w][o])\n", - " b2 = solver.IsLessCstVar(\n", - " solver.Element(rankMen[o], wife[o]), rankMen[o][w])\n", - " solver.Add(b1 - b2 <= 0)\n", + " # forall(w in Women, o in Men)\n", + " # cp.post(rankWomen[w,o] < rankWomen[w,husband[w]] => rankMen[o,wife[o]] <\n", + " # rankMen[o,w]);\n", + " for w in range(n):\n", + " for o in range(n):\n", + " b1 = solver.IsGreaterCstVar(\n", + " solver.Element(rankWomen[w], husband[w]), rankWomen[w][o])\n", + " b2 = solver.IsLessCstVar(\n", + " solver.Element(rankMen[o], wife[o]), rankMen[o][w])\n", + " solver.Add(b1 - b2 <= 0)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(wife)\n", - "solution.Add(husband)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(wife)\n", + " solution.Add(husband)\n", "\n", - "db = solver.Phase(wife + husband, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE)\n", + " db = solver.Phase(wife + husband, solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " solutions = []\n", + " while solver.NextSolution():\n", + " # solutions.append([x[i].Value() for i in range(x_len)])\n", + " print(\"wife : \", [wife[i].Value() for i in range(n)])\n", + " print(\"husband: \", [husband[i].Value() for i in range(n)])\n", + " print()\n", + " num_solutions += 1\n", + "\n", + " solver.EndSearch()\n", "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "solutions = []\n", - "while solver.NextSolution():\n", - " # solutions.append([x[i].Value() for i in range(x_len)])\n", - " print(\"wife : \", [wife[i].Value() for i in range(n)])\n", - " print(\"husband: \", [husband[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", - "print(\"#############\")\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", + " print()\n", "\n", "\n", "#\n", "# From Van Hentenryck's OPL book\n", - "#van_hentenryck = {\n", + "#\n", + "van_hentenryck = {\n", " \"rankWomen\": [[1, 2, 4, 3, 5], [3, 5, 1, 2, 4], [5, 4, 2, 1, 3],\n", " [1, 3, 5, 4, 2], [4, 2, 3, 5, 1]],\n", " \"rankMen\": [[5, 1, 2, 4, 3], [4, 1, 3, 2, 5], [5, 3, 2, 4, 1],\n", @@ -252,6 +247,11 @@ " \"rankMen\": [[1, 4, 2, 5, 6, 3], [3, 4, 6, 1, 5, 2], [1, 6, 4, 2, 3, 5],\n", " [6, 5, 3, 4, 2, 1], [3, 1, 2, 4, 5, 6], [2, 3, 1, 6, 5, 4]]\n", "}\n", + "\n", + "main(van_hentenryck, \"Van Hentenryck\")\n", + "main(mathworld, \"MathWorld\")\n", + "main(problem3, \"Problem 3\")\n", + "main(problem4, \"Problem4\")\n", "\n" ] } diff --git a/examples/notebook/contrib/stable_marriage_sat.ipynb b/examples/notebook/contrib/stable_marriage_sat.ipynb index 88bfaa1f8a..cd3648401f 100644 --- a/examples/notebook/contrib/stable_marriage_sat.ipynb +++ b/examples/notebook/contrib/stable_marriage_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,14 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Solves the stable marriage problem in CP-SAT.\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,20 +82,6 @@ "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", - "\"\"\"Solves the stable marriage problem in CP-SAT.\"\"\"\n", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", @@ -111,66 +105,85 @@ " return self.__solution_count\n", "\n", "\n", - "mrank = ranks[\"rankMen\"]\n", - "wrank = ranks[\"rankWomen\"]\n", + "def main(ranks, pair_num):\n", + " mrank = ranks[\"rankMen\"]\n", + " wrank = ranks[\"rankWomen\"]\n", "\n", - "n = pair_num\n", + " n = pair_num\n", "\n", - "model = cp_model.CpModel()\n", + " model = cp_model.CpModel()\n", "\n", - "wife = [model.NewIntVar(0, n - 1, \"wife[%i]\" % i) for i in range(n)]\n", - "husband = [model.NewIntVar(0, n - 1, \"husband[%i]\" % i) for i in range(n)]\n", + " wife = [model.NewIntVar(0, n - 1, \"wife[%i]\" % i) for i in range(n)]\n", + " husband = [model.NewIntVar(0, n - 1, \"husband[%i]\" % i) for i in range(n)]\n", "\n", - "for m in range(n):\n", - " model.AddElement(wife[m], husband, m)\n", - "\n", - "for w in range(n):\n", - " model.AddElement(husband[w], wife, w)\n", - "\n", - "#mrank[w][m] < mrank[w][husband[w]] => wrank[m][wife[m]] < wrank[m][w]\n", - "for w in range(n):\n", " for m in range(n):\n", - " husband_rank = model.NewIntVar(1, n, \"\")\n", - " model.AddElement(husband[w], mrank[w], husband_rank)\n", + " model.AddElement(wife[m], husband, m)\n", "\n", - " wife_rank = model.NewIntVar(1, n, \"\")\n", - " model.AddElement(wife[m], wrank[m], wife_rank)\n", - "\n", - " husband_dominated = model.NewBoolVar(\"\")\n", - " model.Add(mrank[w][m] < husband_rank).OnlyEnforceIf(husband_dominated)\n", - " model.Add(mrank[w][m] >= husband_rank).OnlyEnforceIf(\n", - " husband_dominated.Not())\n", - "\n", - " wife_dominates = model.NewBoolVar(\"\")\n", - " model.Add(wife_rank < wrank[m][w]).OnlyEnforceIf(wife_dominates)\n", - " model.Add(wife_rank >= wrank[m][w]).OnlyEnforceIf(wife_dominates.Not())\n", - "\n", - " model.AddImplication(husband_dominated, wife_dominates)\n", - "\n", - "#wrank[m][w] < wrank[m][wife[m]] => mrank[w][husband[w]] < mrank[w][m]\n", - "for m in range(n):\n", " for w in range(n):\n", - " wife_rank = model.NewIntVar(1, n, \"\")\n", - " model.AddElement(wife[m], wrank[m], wife_rank)\n", + " model.AddElement(husband[w], wife, w)\n", "\n", - " husband_rank = model.NewIntVar(1, n, \"\")\n", - " model.AddElement(husband[w], mrank[w], husband_rank)\n", + " #mrank[w][m] < mrank[w][husband[w]] => wrank[m][wife[m]] < wrank[m][w]\n", + " for w in range(n):\n", + " for m in range(n):\n", + " husband_rank = model.NewIntVar(1, n, \"\")\n", + " model.AddElement(husband[w], mrank[w], husband_rank)\n", "\n", - " wife_dominated = model.NewBoolVar(\"\")\n", - " model.Add(wrank[m][w] < wife_rank).OnlyEnforceIf(wife_dominated)\n", - " model.Add(wrank[m][w] >= wife_rank).OnlyEnforceIf(wife_dominated.Not())\n", + " wife_rank = model.NewIntVar(1, n, \"\")\n", + " model.AddElement(wife[m], wrank[m], wife_rank)\n", "\n", - " husband_dominates = model.NewBoolVar(\"\")\n", - " model.Add(husband_rank < mrank[w][m]).OnlyEnforceIf(husband_dominates)\n", - " model.Add(husband_rank >= mrank[w][m]).OnlyEnforceIf(\n", - " husband_dominates.Not())\n", + " husband_dominated = model.NewBoolVar(\"\")\n", + " model.Add(mrank[w][m] < husband_rank).OnlyEnforceIf(husband_dominated)\n", + " model.Add(mrank[w][m] >= husband_rank).OnlyEnforceIf(\n", + " husband_dominated.Not())\n", "\n", - " model.AddImplication(wife_dominated, husband_dominates)\n", + " wife_dominates = model.NewBoolVar(\"\")\n", + " model.Add(wife_rank < wrank[m][w]).OnlyEnforceIf(wife_dominates)\n", + " model.Add(wife_rank >= wrank[m][w]).OnlyEnforceIf(wife_dominates.Not())\n", "\n", - "solver = cp_model.CpSolver()\n", - "solution_printer = SolutionPrinter(wife, husband)\n", - "solver.parameters.enumerate_all_solutions = True\n", - "solver.Solve(model, solution_printer)\n", + " model.AddImplication(husband_dominated, wife_dominates)\n", + "\n", + " #wrank[m][w] < wrank[m][wife[m]] => mrank[w][husband[w]] < mrank[w][m]\n", + " for m in range(n):\n", + " for w in range(n):\n", + " wife_rank = model.NewIntVar(1, n, \"\")\n", + " model.AddElement(wife[m], wrank[m], wife_rank)\n", + "\n", + " husband_rank = model.NewIntVar(1, n, \"\")\n", + " model.AddElement(husband[w], mrank[w], husband_rank)\n", + "\n", + " wife_dominated = model.NewBoolVar(\"\")\n", + " model.Add(wrank[m][w] < wife_rank).OnlyEnforceIf(wife_dominated)\n", + " model.Add(wrank[m][w] >= wife_rank).OnlyEnforceIf(wife_dominated.Not())\n", + "\n", + " husband_dominates = model.NewBoolVar(\"\")\n", + " model.Add(husband_rank < mrank[w][m]).OnlyEnforceIf(husband_dominates)\n", + " model.Add(husband_rank >= mrank[w][m]).OnlyEnforceIf(\n", + " husband_dominates.Not())\n", + "\n", + " model.AddImplication(wife_dominated, husband_dominates)\n", + "\n", + " solver = cp_model.CpSolver()\n", + " solution_printer = SolutionPrinter(wife, husband)\n", + " solver.parameters.enumerate_all_solutions = True\n", + " solver.Solve(model, solution_printer)\n", + "\n", + "\n", + "rankings1 = {\n", + " \"rankMen\": [[1, 2, 3, 4], [4, 3, 2, 1], [1, 2, 3, 4], [3, 4, 1, 2]],\n", + " \"rankWomen\": [[1, 2, 3, 4], [2, 1, 3, 4], [1, 4, 3, 2], [4, 3, 1, 2]]\n", + "}\n", + "\n", + "rankings2 = {\n", + " \"rankMen\": [[1, 5, 4, 6, 2, 3], [4, 1, 5, 2, 6, 3], [6, 4, 2, 1, 5, 3],\n", + " [1, 5, 2, 4, 3, 6], [4, 2, 1, 5, 6, 3], [2, 6, 3, 5, 1, 4]],\n", + " \"rankWomen\": [[1, 4, 2, 5, 6, 3], [3, 4, 6, 1, 5, 2], [1, 6, 4, 2, 3, 5],\n", + " [6, 5, 3, 4, 2, 1], [3, 1, 2, 4, 5, 6], [2, 3, 1, 6, 5, 4]]\n", + "}\n", + "\n", + "problem = rankings2\n", + "couple_count = len(problem[\"rankMen\"])\n", + "\n", + "main(problem, couple_count)\n", "\n" ] } diff --git a/examples/notebook/contrib/steel.ipynb b/examples/notebook/contrib/steel.ipynb index afcaddbe7a..85f57e3e34 100644 --- a/examples/notebook/contrib/steel.ipynb +++ b/examples/notebook/contrib/steel.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -217,46 +217,50 @@ " return 'SteelMillDecisionBuilder(' + str(self.__x) + ')'\n", "\n", "\n", - "#------------------solver and variable declaration-------------\n", - "(nb_slabs, capacity, max_capacity, weights, colors, loss, color_orders) =\\\n", - " ReadData(args.data)\n", - "nb_colors = len(color_orders)\n", - "solver = pywrapcp.Solver('Steel Mill Slab')\n", - "x = [solver.IntVar(0, nb_slabs - 1, 'x' + str(i)) for i in range(nb_slabs)]\n", - "load_vars = [\n", - " solver.IntVar(0, max_capacity - 1, 'load_vars' + str(i))\n", - " for i in range(nb_slabs)\n", - "]\n", + "def main(args):\n", + " #------------------solver and variable declaration-------------\n", + " (nb_slabs, capacity, max_capacity, weights, colors, loss, color_orders) =\\\n", + " ReadData(args.data)\n", + " nb_colors = len(color_orders)\n", + " solver = pywrapcp.Solver('Steel Mill Slab')\n", + " x = [solver.IntVar(0, nb_slabs - 1, 'x' + str(i)) for i in range(nb_slabs)]\n", + " load_vars = [\n", + " solver.IntVar(0, max_capacity - 1, 'load_vars' + str(i))\n", + " for i in range(nb_slabs)\n", + " ]\n", "\n", - "#-------------------post of the constraints--------------\n", + " #-------------------post of the constraints--------------\n", "\n", - "# Bin Packing.\n", - "BinPacking(solver, x, weights, load_vars)\n", - "# At most two colors per slab.\n", - "for s in range(nb_slabs):\n", - " solver.Add(\n", - " solver.SumLessOrEqual([\n", - " solver.Max([solver.IsEqualCstVar(x[c], s)\n", - " for c in o])\n", - " for o in color_orders\n", - " ], 2))\n", + " # Bin Packing.\n", + " BinPacking(solver, x, weights, load_vars)\n", + " # At most two colors per slab.\n", + " for s in range(nb_slabs):\n", + " solver.Add(\n", + " solver.SumLessOrEqual([\n", + " solver.Max([solver.IsEqualCstVar(x[c], s)\n", + " for c in o])\n", + " for o in color_orders\n", + " ], 2))\n", "\n", - "#----------------Objective-------------------------------\n", + " #----------------Objective-------------------------------\n", "\n", - "objective_var = \\\n", - " solver.Sum([load_vars[s].IndexOf(loss) for s in range(nb_slabs)]).Var()\n", - "objective = solver.Minimize(objective_var, 1)\n", + " objective_var = \\\n", + " solver.Sum([load_vars[s].IndexOf(loss) for s in range(nb_slabs)]).Var()\n", + " objective = solver.Minimize(objective_var, 1)\n", "\n", - "#------------start the search and optimization-----------\n", + " #------------start the search and optimization-----------\n", "\n", - "db = SteelDecisionBuilder(x, nb_slabs, weights, loss, load_vars)\n", - "search_log = solver.SearchLog(100000, objective_var)\n", - "global_limit = solver.TimeLimit(args.time_limit)\n", - "solver.NewSearch(db, [objective, search_log, global_limit])\n", - "while solver.NextSolution():\n", - " print('Objective:', objective_var.Value(),\\\n", - " 'check:', sum(loss[load_vars[s].Min()] for s in range(nb_slabs)))\n", - "solver.EndSearch()\n", + " db = SteelDecisionBuilder(x, nb_slabs, weights, loss, load_vars)\n", + " search_log = solver.SearchLog(100000, objective_var)\n", + " global_limit = solver.TimeLimit(args.time_limit)\n", + " solver.NewSearch(db, [objective, search_log, global_limit])\n", + " while solver.NextSolution():\n", + " print('Objective:', objective_var.Value(),\\\n", + " 'check:', sum(loss[load_vars[s].Min()] for s in range(nb_slabs)))\n", + " solver.EndSearch()\n", + "\n", + "\n", + "main(parser.parse_args())\n", "\n" ] } diff --git a/examples/notebook/contrib/steel_lns.ipynb b/examples/notebook/contrib/steel_lns.ipynb index 3a36a89186..601f5feeb4 100644 --- a/examples/notebook/contrib/steel_lns.ipynb +++ b/examples/notebook/contrib/steel_lns.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -258,77 +258,81 @@ "# ----------- Main Function -----------\n", "\n", "\n", - "# ----- solver and variable declaration -----\n", - "(nb_slabs, capacity, max_capacity, weights, colors, loss, color_orders) =\\\n", - " ReadData(args.data)\n", - "nb_colors = len(color_orders)\n", - "solver = pywrapcp.Solver('Steel Mill Slab')\n", - "x = [solver.IntVar(0, nb_slabs - 1, 'x' + str(i)) for i in range(nb_slabs)]\n", - "load_vars = [\n", - " solver.IntVar(0, max_capacity - 1, 'load_vars' + str(i))\n", - " for i in range(nb_slabs)\n", - "]\n", + "def main(args):\n", + " # ----- solver and variable declaration -----\n", + " (nb_slabs, capacity, max_capacity, weights, colors, loss, color_orders) =\\\n", + " ReadData(args.data)\n", + " nb_colors = len(color_orders)\n", + " solver = pywrapcp.Solver('Steel Mill Slab')\n", + " x = [solver.IntVar(0, nb_slabs - 1, 'x' + str(i)) for i in range(nb_slabs)]\n", + " load_vars = [\n", + " solver.IntVar(0, max_capacity - 1, 'load_vars' + str(i))\n", + " for i in range(nb_slabs)\n", + " ]\n", "\n", - "# ----- post of the constraints -----\n", + " # ----- post of the constraints -----\n", "\n", - "# Bin Packing.\n", - "BinPacking(solver, x, weights, load_vars)\n", - "# At most two colors per slab.\n", - "for s in range(nb_slabs):\n", - " solver.Add(\n", - " solver.SumLessOrEqual([\n", - " solver.Max([solver.IsEqualCstVar(x[c], s)\n", - " for c in o])\n", - " for o in color_orders\n", - " ], 2))\n", + " # Bin Packing.\n", + " BinPacking(solver, x, weights, load_vars)\n", + " # At most two colors per slab.\n", + " for s in range(nb_slabs):\n", + " solver.Add(\n", + " solver.SumLessOrEqual([\n", + " solver.Max([solver.IsEqualCstVar(x[c], s)\n", + " for c in o])\n", + " for o in color_orders\n", + " ], 2))\n", "\n", - "# ----- Objective -----\n", + " # ----- Objective -----\n", "\n", - "objective_var = \\\n", - " solver.Sum([load_vars[s].IndexOf(loss) for s in range(nb_slabs)]).Var()\n", - "objective = solver.Minimize(objective_var, 1)\n", + " objective_var = \\\n", + " solver.Sum([load_vars[s].IndexOf(loss) for s in range(nb_slabs)]).Var()\n", + " objective = solver.Minimize(objective_var, 1)\n", "\n", - "# ----- start the search and optimization -----\n", + " # ----- start the search and optimization -----\n", "\n", - "assign_db = SteelDecisionBuilder(x, nb_slabs, weights, loss, load_vars)\n", - "first_solution = solver.Assignment()\n", - "first_solution.Add(x)\n", - "first_solution.AddObjective(objective_var)\n", - "store_db = solver.StoreAssignment(first_solution)\n", - "first_solution_db = solver.Compose([assign_db, store_db])\n", - "print('searching for initial solution,', end=' ')\n", - "solver.Solve(first_solution_db)\n", - "print('initial cost =', first_solution.ObjectiveValue())\n", + " assign_db = SteelDecisionBuilder(x, nb_slabs, weights, loss, load_vars)\n", + " first_solution = solver.Assignment()\n", + " first_solution.Add(x)\n", + " first_solution.AddObjective(objective_var)\n", + " store_db = solver.StoreAssignment(first_solution)\n", + " first_solution_db = solver.Compose([assign_db, store_db])\n", + " print('searching for initial solution,', end=' ')\n", + " solver.Solve(first_solution_db)\n", + " print('initial cost =', first_solution.ObjectiveValue())\n", "\n", - "# To search a fragment, we use a basic randomized decision builder.\n", - "# We can also use assign_db instead of inner_db.\n", - "inner_db = solver.Phase(x, solver.CHOOSE_RANDOM, solver.ASSIGN_MIN_VALUE)\n", - "# The most important aspect is to limit the time exploring each fragment.\n", - "inner_limit = solver.FailuresLimit(args.lns_fail_limit)\n", - "continuation_db = solver.SolveOnce(inner_db, [inner_limit])\n", + " # To search a fragment, we use a basic randomized decision builder.\n", + " # We can also use assign_db instead of inner_db.\n", + " inner_db = solver.Phase(x, solver.CHOOSE_RANDOM, solver.ASSIGN_MIN_VALUE)\n", + " # The most important aspect is to limit the time exploring each fragment.\n", + " inner_limit = solver.FailuresLimit(args.lns_fail_limit)\n", + " continuation_db = solver.SolveOnce(inner_db, [inner_limit])\n", "\n", - "# Now, we create the LNS objects.\n", - "rand = random.Random()\n", - "rand.seed(args.lns_random_seed)\n", - "local_search_operator = SteelRandomLns(x, rand, args.lns_fragment_size)\n", - "# This is in fact equivalent to the following predefined LNS operator:\n", - "# local_search_operator = solver.RandomLNSOperator(x,\n", - "# args.lns_fragment_size,\n", - "# args.lns_random_seed)\n", - "local_search_parameters = solver.LocalSearchPhaseParameters(\n", - " objective_var, local_search_operator, continuation_db)\n", - "local_search_db = solver.LocalSearchPhase(first_solution,\n", - " local_search_parameters)\n", - "global_limit = solver.TimeLimit(args.time_limit)\n", + " # Now, we create the LNS objects.\n", + " rand = random.Random()\n", + " rand.seed(args.lns_random_seed)\n", + " local_search_operator = SteelRandomLns(x, rand, args.lns_fragment_size)\n", + " # This is in fact equivalent to the following predefined LNS operator:\n", + " # local_search_operator = solver.RandomLNSOperator(x,\n", + " # args.lns_fragment_size,\n", + " # args.lns_random_seed)\n", + " local_search_parameters = solver.LocalSearchPhaseParameters(\n", + " objective_var, local_search_operator, continuation_db)\n", + " local_search_db = solver.LocalSearchPhase(first_solution,\n", + " local_search_parameters)\n", + " global_limit = solver.TimeLimit(args.time_limit)\n", "\n", - "print('using LNS to improve the initial solution')\n", + " print('using LNS to improve the initial solution')\n", "\n", - "search_log = solver.SearchLog(100000, objective_var)\n", - "solver.NewSearch(local_search_db, [objective, search_log, global_limit])\n", - "while solver.NextSolution():\n", - " print('Objective:', objective_var.Value(),\\\n", - " 'check:', sum(loss[load_vars[s].Min()] for s in range(nb_slabs)))\n", - "solver.EndSearch()\n", + " search_log = solver.SearchLog(100000, objective_var)\n", + " solver.NewSearch(local_search_db, [objective, search_log, global_limit])\n", + " while solver.NextSolution():\n", + " print('Objective:', objective_var.Value(),\\\n", + " 'check:', sum(loss[load_vars[s].Min()] for s in range(nb_slabs)))\n", + " solver.EndSearch()\n", + "\n", + "\n", + "main(parser.parse_args())\n", "\n" ] } diff --git a/examples/notebook/contrib/stigler_contrib.ipynb b/examples/notebook/contrib/stigler_contrib.ipynb index 07e7f23e9a..7cf68f7e9d 100644 --- a/examples/notebook/contrib/stigler_contrib.ipynb +++ b/examples/notebook/contrib/stigler_contrib.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Original Stigler's 1939 diet problem Google or-tools.\n", "\n", @@ -191,227 +176,247 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(sol=\"CBC\"):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "print(\"Solver: \", sol)\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", + " # 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", - "# commodities\n", - "num_commodities = 77\n", - "C = list(range(num_commodities))\n", + " #\n", + " # data\n", + " #\n", + " # commodities\n", + " num_commodities = 77\n", + " C = list(range(num_commodities))\n", "\n", - "# days in a year\n", - "days = 365.25\n", + " # days in a year\n", + " days = 365.25\n", "\n", - "# nutrients\n", - "num_nutrients = 9\n", - "N = list(range(num_nutrients))\n", + " # nutrients\n", + " num_nutrients = 9\n", + " N = list(range(num_nutrients))\n", "\n", - "nutrients = [\n", - " \"calories\", # Calories, unit = 1000\n", - " \"protein\", # Protein, unit = grams\n", - " \"calcium\", # Calcium, unit = grams\n", - " \"iron\", # Iron, unit = milligrams\n", - " \"vitaminA\", # Vitamin A, unit = 1000 International Units\n", - " \"thiamine\", # Thiamine, Vit. B1, unit = milligrams\n", - " \"riboflavin\", # Riboflavin, Vit. B2, unit = milligrams\n", - " \"niacin\", # Niacin (Nicotinic Acid), unit = milligrams\n", - " \"ascorbicAcid\" # Ascorbic Acid, Vit. C, unit = milligrams\n", - "]\n", + " nutrients = [\n", + " \"calories\", # Calories, unit = 1000\n", + " \"protein\", # Protein, unit = grams\n", + " \"calcium\", # Calcium, unit = grams\n", + " \"iron\", # Iron, unit = milligrams\n", + " \"vitaminA\", # Vitamin A, unit = 1000 International Units\n", + " \"thiamine\", # Thiamine, Vit. B1, unit = milligrams\n", + " \"riboflavin\", # Riboflavin, Vit. B2, unit = milligrams\n", + " \"niacin\", # Niacin (Nicotinic Acid), unit = milligrams\n", + " \"ascorbicAcid\" # Ascorbic Acid, Vit. C, unit = milligrams\n", + " ]\n", "\n", - "commodities = [[\"Wheat Flour (Enriched)\", \"10 lb.\"], [\"Macaroni\", \"1 lb.\"],\n", - " [\"Wheat Cereal (Enriched)\",\n", - " \"28 oz.\"], [\"Corn Flakes\", \"8 oz.\"], [\"Corn Meal\", \"1 lb.\"],\n", - " [\"Hominy Grits\", \"24 oz.\"], [\"Rice\", \"1 lb.\"],\n", - " [\"Rolled Oats\", \"1 lb.\"], [\"White Bread (Enriched)\", \"1 lb.\"],\n", - " [\"Whole Wheat Bread\", \"1 lb.\"], [\"Rye Bread\", \"1 lb.\"],\n", - " [\"Pound Cake\", \"1 lb.\"], [\"Soda Crackers\", \"1 lb.\"],\n", - " [\"Milk\", \"1 qt.\"], [\"Evaporated Milk (can)\", \"14.5 oz.\"],\n", - " [\"Butter\", \"1 lb.\"], [\"Oleomargarine\", \"1 lb.\"],\n", - " [\"Eggs\", \"1 doz.\"], [\"Cheese (Cheddar)\", \"1 lb.\"],\n", - " [\"Cream\", \"1/2 pt.\"], [\"Peanut Butter\", \"1 lb.\"],\n", - " [\"Mayonnaise\", \"1/2 pt.\"], [\"Crisco\", \"1 lb.\"],\n", - " [\"Lard\", \"1 lb.\"], [\"Sirloin Steak\", \"1 lb.\"],\n", - " [\"Round Steak\", \"1 lb.\"], [\"Rib Roast\", \"1 lb.\"],\n", - " [\"Chuck Roast\", \"1 lb.\"], [\"Plate\", \"1 lb.\"],\n", - " [\"Liver (Beef)\", \"1 lb.\"], [\"Leg of Lamb\", \"1 lb.\"],\n", - " [\"Lamb Chops (Rib)\", \"1 lb.\"], [\"Pork Chops\", \"1 lb.\"],\n", - " [\"Pork Loin Roast\", \"1 lb.\"], [\"Bacon\", \"1 lb.\"],\n", - " [\"Ham - smoked\", \"1 lb.\"], [\"Salt Pork\", \"1 lb.\"],\n", - " [\"Roasting Chicken\", \"1 lb.\"], [\"Veal Cutlets\", \"1 lb.\"],\n", - " [\"Salmon, Pink (can)\", \"16 oz.\"], [\"Apples\", \"1 lb.\"],\n", - " [\"Bananas\", \"1 lb.\"], [\"Lemons\", \"1 doz.\"],\n", - " [\"Oranges\", \"1 doz.\"], [\"Green Beans\", \"1 lb.\"],\n", - " [\"Cabbage\", \"1 lb.\"], [\"Carrots\", \"1 bunch\"],\n", - " [\"Celery\", \"1 stalk\"], [\"Lettuce\", \"1 head\"],\n", - " [\"Onions\", \"1 lb.\"], [\"Potatoes\", \"15 lb.\"],\n", - " [\"Spinach\", \"1 lb.\"], [\"Sweet Potatoes\", \"1 lb.\"],\n", - " [\"Peaches (can)\", \"No. 2 1/2\"], [\"Pears (can)\", \"No. 2 1/2,\"],\n", - " [\"Pineapple (can)\", \"No. 2 1/2\"], [\"Asparagus (can)\", \"No. 2\"],\n", - " [\"Grean Beans (can)\", \"No. 2\"],\n", - " [\"Pork and Beans (can)\", \"16 oz.\"], [\"Corn (can)\", \"No. 2\"],\n", - " [\"Peas (can)\", \"No. 2\"], [\"Tomatoes (can)\", \"No. 2\"],\n", - " [\"Tomato Soup (can)\", \"10 1/2 oz.\"],\n", - " [\"Peaches, Dried\", \"1 lb.\"], [\"Prunes, Dried\", \"1 lb.\"],\n", - " [\"Raisins, Dried\", \"15 oz.\"], [\"Peas, Dried\", \"1 lb.\"],\n", - " [\"Lima Beans, Dried\", \"1 lb.\"], [\"Navy Beans, Dried\", \"1 lb.\"],\n", - " [\"Coffee\", \"1 lb.\"], [\"Tea\", \"1/4 lb.\"], [\"Cocoa\", \"8 oz.\"],\n", - " [\"Chocolate\", \"8 oz.\"], [\"Sugar\", \"10 lb.\"],\n", - " [\"Corn Sirup\", \"24 oz.\"], [\"Molasses\", \"18 oz.\"],\n", - " [\"Strawberry Preserve\", \"1 lb.\"]]\n", + " commodities = [[\"Wheat Flour (Enriched)\", \"10 lb.\"], [\"Macaroni\", \"1 lb.\"],\n", + " [\"Wheat Cereal (Enriched)\",\n", + " \"28 oz.\"], [\"Corn Flakes\", \"8 oz.\"], [\"Corn Meal\", \"1 lb.\"],\n", + " [\"Hominy Grits\", \"24 oz.\"], [\"Rice\", \"1 lb.\"],\n", + " [\"Rolled Oats\", \"1 lb.\"], [\"White Bread (Enriched)\", \"1 lb.\"],\n", + " [\"Whole Wheat Bread\", \"1 lb.\"], [\"Rye Bread\", \"1 lb.\"],\n", + " [\"Pound Cake\", \"1 lb.\"], [\"Soda Crackers\", \"1 lb.\"],\n", + " [\"Milk\", \"1 qt.\"], [\"Evaporated Milk (can)\", \"14.5 oz.\"],\n", + " [\"Butter\", \"1 lb.\"], [\"Oleomargarine\", \"1 lb.\"],\n", + " [\"Eggs\", \"1 doz.\"], [\"Cheese (Cheddar)\", \"1 lb.\"],\n", + " [\"Cream\", \"1/2 pt.\"], [\"Peanut Butter\", \"1 lb.\"],\n", + " [\"Mayonnaise\", \"1/2 pt.\"], [\"Crisco\", \"1 lb.\"],\n", + " [\"Lard\", \"1 lb.\"], [\"Sirloin Steak\", \"1 lb.\"],\n", + " [\"Round Steak\", \"1 lb.\"], [\"Rib Roast\", \"1 lb.\"],\n", + " [\"Chuck Roast\", \"1 lb.\"], [\"Plate\", \"1 lb.\"],\n", + " [\"Liver (Beef)\", \"1 lb.\"], [\"Leg of Lamb\", \"1 lb.\"],\n", + " [\"Lamb Chops (Rib)\", \"1 lb.\"], [\"Pork Chops\", \"1 lb.\"],\n", + " [\"Pork Loin Roast\", \"1 lb.\"], [\"Bacon\", \"1 lb.\"],\n", + " [\"Ham - smoked\", \"1 lb.\"], [\"Salt Pork\", \"1 lb.\"],\n", + " [\"Roasting Chicken\", \"1 lb.\"], [\"Veal Cutlets\", \"1 lb.\"],\n", + " [\"Salmon, Pink (can)\", \"16 oz.\"], [\"Apples\", \"1 lb.\"],\n", + " [\"Bananas\", \"1 lb.\"], [\"Lemons\", \"1 doz.\"],\n", + " [\"Oranges\", \"1 doz.\"], [\"Green Beans\", \"1 lb.\"],\n", + " [\"Cabbage\", \"1 lb.\"], [\"Carrots\", \"1 bunch\"],\n", + " [\"Celery\", \"1 stalk\"], [\"Lettuce\", \"1 head\"],\n", + " [\"Onions\", \"1 lb.\"], [\"Potatoes\", \"15 lb.\"],\n", + " [\"Spinach\", \"1 lb.\"], [\"Sweet Potatoes\", \"1 lb.\"],\n", + " [\"Peaches (can)\", \"No. 2 1/2\"], [\"Pears (can)\", \"No. 2 1/2,\"],\n", + " [\"Pineapple (can)\", \"No. 2 1/2\"], [\"Asparagus (can)\", \"No. 2\"],\n", + " [\"Grean Beans (can)\", \"No. 2\"],\n", + " [\"Pork and Beans (can)\", \"16 oz.\"], [\"Corn (can)\", \"No. 2\"],\n", + " [\"Peas (can)\", \"No. 2\"], [\"Tomatoes (can)\", \"No. 2\"],\n", + " [\"Tomato Soup (can)\", \"10 1/2 oz.\"],\n", + " [\"Peaches, Dried\", \"1 lb.\"], [\"Prunes, Dried\", \"1 lb.\"],\n", + " [\"Raisins, Dried\", \"15 oz.\"], [\"Peas, Dried\", \"1 lb.\"],\n", + " [\"Lima Beans, Dried\", \"1 lb.\"], [\"Navy Beans, Dried\", \"1 lb.\"],\n", + " [\"Coffee\", \"1 lb.\"], [\"Tea\", \"1/4 lb.\"], [\"Cocoa\", \"8 oz.\"],\n", + " [\"Chocolate\", \"8 oz.\"], [\"Sugar\", \"10 lb.\"],\n", + " [\"Corn Sirup\", \"24 oz.\"], [\"Molasses\", \"18 oz.\"],\n", + " [\"Strawberry Preserve\", \"1 lb.\"]]\n", "\n", - "# price and weight are the two first columns\n", - "data = [\n", - " [36.0, 12600.0, 44.7, 1411.0, 2.0, 365.0, 0.0, 55.4, 33.3, 441.0, 0.0],\n", - " [14.1, 3217.0, 11.6, 418.0, 0.7, 54.0, 0.0, 3.2, 1.9, 68.0, 0.0],\n", - " [24.2, 3280.0, 11.8, 377.0, 14.4, 175.0, 0.0, 14.4, 8.8, 114.0, 0.0],\n", - " [7.1, 3194.0, 11.4, 252.0, 0.1, 56.0, 0.0, 13.5, 2.3, 68.0, 0.0],\n", - " [4.6, 9861.0, 36.0, 897.0, 1.7, 99.0, 30.9, 17.4, 7.9, 106.0, 0.0],\n", - " [8.5, 8005.0, 28.6, 680.0, 0.8, 80.0, 0.0, 10.6, 1.6, 110.0, 0.0],\n", - " [7.5, 6048.0, 21.2, 460.0, 0.6, 41.0, 0.0, 2.0, 4.8, 60.0, 0.0],\n", - " [7.1, 6389.0, 25.3, 907.0, 5.1, 341.0, 0.0, 37.1, 8.9, 64.0, 0.0],\n", - " [7.9, 5742.0, 15.6, 488.0, 2.5, 115.0, 0.0, 13.8, 8.5, 126.0, 0.0],\n", - " [9.1, 4985.0, 12.2, 484.0, 2.7, 125.0, 0.0, 13.9, 6.4, 160.0, 0.0],\n", - " [9.2, 4930.0, 12.4, 439.0, 1.1, 82.0, 0.0, 9.9, 3.0, 66.0, 0.0],\n", - " [24.8, 1829.0, 8.0, 130.0, 0.4, 31.0, 18.9, 2.8, 3.0, 17.0, 0.0],\n", - " [15.1, 3004.0, 12.5, 288.0, 0.5, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", - " [11.0, 8867.0, 6.1, 310.0, 10.5, 18.0, 16.8, 4.0, 16.0, 7.0, 177.0],\n", - " [6.7, 6035.0, 8.4, 422.0, 15.1, 9.0, 26.0, 3.0, 23.5, 11.0, 60.0],\n", - " [20.8, 1473.0, 10.8, 9.0, 0.2, 3.0, 44.2, 0.0, 0.2, 2.0, 0.0],\n", - " [16.1, 2817.0, 20.6, 17.0, 0.6, 6.0, 55.8, 0.2, 0.0, 0.0, 0.0],\n", - " [32.6, 1857.0, 2.9, 238.0, 1.0, 52.0, 18.6, 2.8, 6.5, 1.0, 0.0],\n", - " [24.2, 1874.0, 7.4, 448.0, 16.4, 19.0, 28.1, 0.8, 10.3, 4.0, 0.0],\n", - " [14.1, 1689.0, 3.5, 49.0, 1.7, 3.0, 16.9, 0.6, 2.5, 0.0, 17.0],\n", - " [17.9, 2534.0, 15.7, 661.0, 1.0, 48.0, 0.0, 9.6, 8.1, 471.0, 0.0],\n", - " [16.7, 1198.0, 8.6, 18.0, 0.2, 8.0, 2.7, 0.4, 0.5, 0.0, 0.0],\n", - " [20.3, 2234.0, 20.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", - " [9.8, 4628.0, 41.7, 0.0, 0.0, 0.0, 0.2, 0.0, 0.5, 5.0, 0.0],\n", - " [39.6, 1145.0, 2.9, 166.0, 0.1, 34.0, 0.2, 2.1, 2.9, 69.0, 0.0],\n", - " [36.4, 1246.0, 2.2, 214.0, 0.1, 32.0, 0.4, 2.5, 2.4, 87.0, 0.0],\n", - " [29.2, 1553.0, 3.4, 213.0, 0.1, 33.0, 0.0, 0.0, 2.0, 0.0, 0.0],\n", - " [22.6, 2007.0, 3.6, 309.0, 0.2, 46.0, 0.4, 1.0, 4.0, 120.0, 0.0],\n", - " [14.6, 3107.0, 8.5, 404.0, 0.2, 62.0, 0.0, 0.9, 0.0, 0.0, 0.0],\n", - " [26.8, 1692.0, 2.2, 333.0, 0.2, 139.0, 169.2, 6.4, 50.8, 316.0, 525.0],\n", - " [27.6, 1643.0, 3.1, 245.0, 0.1, 20.0, 0.0, 2.8, 3.0, 86.0, 0.0],\n", - " [36.6, 1239.0, 3.3, 140.0, 0.1, 15.0, 0.0, 1.7, 2.7, 54.0, 0.0],\n", - " [30.7, 1477.0, 3.5, 196.0, 0.2, 80.0, 0.0, 17.4, 2.7, 60.0, 0.0],\n", - " [24.2, 1874.0, 4.4, 249.0, 0.3, 37.0, 0.0, 18.2, 3.6, 79.0, 0.0],\n", - " [25.6, 1772.0, 10.4, 152.0, 0.2, 23.0, 0.0, 1.8, 1.8, 71.0, 0.0],\n", - " [27.4, 1655.0, 6.7, 212.0, 0.2, 31.0, 0.0, 9.9, 3.3, 50.0, 0.0],\n", - " [16.0, 2835.0, 18.8, 164.0, 0.1, 26.0, 0.0, 1.4, 1.8, 0.0, 0.0],\n", - " [30.3, 1497.0, 1.8, 184.0, 0.1, 30.0, 0.1, 0.9, 1.8, 68.0, 46.0],\n", - " [42.3, 1072.0, 1.7, 156.0, 0.1, 24.0, 0.0, 1.4, 2.4, 57.0, 0.0],\n", - " [13.0, 3489.0, 5.8, 705.0, 6.8, 45.0, 3.5, 1.0, 4.9, 209.0, 0.0],\n", - " [4.4, 9072.0, 5.8, 27.0, 0.5, 36.0, 7.3, 3.6, 2.7, 5.0, 544.0],\n", - " [6.1, 4982.0, 4.9, 60.0, 0.4, 30.0, 17.4, 2.5, 3.5, 28.0, 498.0],\n", - " [26.0, 2380.0, 1.0, 21.0, 0.5, 14.0, 0.0, 0.5, 0.0, 4.0, 952.0],\n", - " [30.9, 4439.0, 2.2, 40.0, 1.1, 18.0, 11.1, 3.6, 1.3, 10.0, 1993.0],\n", - " [7.1, 5750.0, 2.4, 138.0, 3.7, 80.0, 69.0, 4.3, 5.8, 37.0, 862.0],\n", - " [3.7, 8949.0, 2.6, 125.0, 4.0, 36.0, 7.2, 9.0, 4.5, 26.0, 5369.0],\n", - " [4.7, 6080.0, 2.7, 73.0, 2.8, 43.0, 188.5, 6.1, 4.3, 89.0, 608.0],\n", - " [7.3, 3915.0, 0.9, 51.0, 3.0, 23.0, 0.9, 1.4, 1.4, 9.0, 313.0],\n", - " [8.2, 2247.0, 0.4, 27.0, 1.1, 22.0, 112.4, 1.8, 3.4, 11.0, 449.0],\n", - " [3.6, 11844.0, 5.8, 166.0, 3.8, 59.0, 16.6, 4.7, 5.9, 21.0, 1184.0],\n", - " [34.0, 16810.0, 14.3, 336.0, 1.8, 118.0, 6.7, 29.4, 7.1, 198.0, 2522.0],\n", - " [8.1, 4592.0, 1.1, 106.0, 0.0, 138.0, 918.4, 5.7, 13.8, 33.0, 2755.0],\n", - " [5.1, 7649.0, 9.6, 138.0, 2.7, 54.0, 290.7, 8.4, 5.4, 83.0, 1912.0],\n", - " [16.8, 4894.0, 3.7, 20.0, 0.4, 10.0, 21.5, 0.5, 1.0, 31.0, 196.0],\n", - " [20.4, 4030.0, 3.0, 8.0, 0.3, 8.0, 0.8, 0.8, 0.8, 5.0, 81.0],\n", - " [21.3, 3993.0, 2.4, 16.0, 0.4, 8.0, 2.0, 2.8, 0.8, 7.0, 399.0],\n", - " [27.7, 1945.0, 0.4, 33.0, 0.3, 12.0, 16.3, 1.4, 2.1, 17.0, 272.0],\n", - " [10.0, 5386.0, 1.0, 54.0, 2.0, 65.0, 53.9, 1.6, 4.3, 32.0, 431.0],\n", - " [7.1, 6389.0, 7.5, 364.0, 4.0, 134.0, 3.5, 8.3, 7.7, 56.0, 0.0],\n", - " [10.4, 5452.0, 5.2, 136.0, 0.2, 16.0, 12.0, 1.6, 2.7, 42.0, 218.0],\n", - " [13.8, 4109.0, 2.3, 136.0, 0.6, 45.0, 34.9, 4.9, 2.5, 37.0, 370.0],\n", - " [8.6, 6263.0, 1.3, 63.0, 0.7, 38.0, 53.2, 3.4, 2.5, 36.0, 1253.0],\n", - " [7.6, 3917.0, 1.6, 71.0, 0.6, 43.0, 57.9, 3.5, 2.4, 67.0, 862.0],\n", - " [15.7, 2889.0, 8.5, 87.0, 1.7, 173.0, 86.8, 1.2, 4.3, 55.0, 57.0],\n", - " [9.0, 4284.0, 12.8, 99.0, 2.5, 154.0, 85.7, 3.9, 4.3, 65.0, 257.0],\n", - " [9.4, 4524.0, 13.5, 104.0, 2.5, 136.0, 4.5, 6.3, 1.4, 24.0, 136.0],\n", - " [7.9, 5742.0, 20.0, 1367.0, 4.2, 345.0, 2.9, 28.7, 18.4, 162.0, 0.0],\n", - " [8.9, 5097.0, 17.4, 1055.0, 3.7, 459.0, 5.1, 26.9, 38.2, 93.0, 0.0],\n", - " [5.9, 7688.0, 26.9, 1691.0, 11.4, 792.0, 0.0, 38.4, 24.6, 217.0, 0.0],\n", - " [22.4, 2025.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 5.1, 50.0, 0.0],\n", - " [17.4, 652.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.3, 42.0, 0.0],\n", - " [8.6, 2637.0, 8.7, 237.0, 3.0, 72.0, 0.0, 2.0, 11.9, 40.0, 0.0],\n", - " [16.2, 1400.0, 8.0, 77.0, 1.3, 39.0, 0.0, 0.9, 3.4, 14.0, 0.0],\n", - " [51.7, 8773.0, 34.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", - " [13.7, 4996.0, 14.7, 0.0, 0.5, 74.0, 0.0, 0.0, 0.0, 5.0, 0.0],\n", - " [13.6, 3752.0, 9.0, 0.0, 10.3, 244.0, 0.0, 1.9, 7.5, 146.0, 0.0],\n", - " [20.5, 2213.0, 6.4, 11.0, 0.4, 7.0, 0.2, 0.2, 0.4, 3.0, 0.0]\n", - "]\n", + " # price and weight are the two first columns\n", + " data = [\n", + " [36.0, 12600.0, 44.7, 1411.0, 2.0, 365.0, 0.0, 55.4, 33.3, 441.0, 0.0],\n", + " [14.1, 3217.0, 11.6, 418.0, 0.7, 54.0, 0.0, 3.2, 1.9, 68.0, 0.0],\n", + " [24.2, 3280.0, 11.8, 377.0, 14.4, 175.0, 0.0, 14.4, 8.8, 114.0, 0.0],\n", + " [7.1, 3194.0, 11.4, 252.0, 0.1, 56.0, 0.0, 13.5, 2.3, 68.0, 0.0],\n", + " [4.6, 9861.0, 36.0, 897.0, 1.7, 99.0, 30.9, 17.4, 7.9, 106.0, 0.0],\n", + " [8.5, 8005.0, 28.6, 680.0, 0.8, 80.0, 0.0, 10.6, 1.6, 110.0, 0.0],\n", + " [7.5, 6048.0, 21.2, 460.0, 0.6, 41.0, 0.0, 2.0, 4.8, 60.0, 0.0],\n", + " [7.1, 6389.0, 25.3, 907.0, 5.1, 341.0, 0.0, 37.1, 8.9, 64.0, 0.0],\n", + " [7.9, 5742.0, 15.6, 488.0, 2.5, 115.0, 0.0, 13.8, 8.5, 126.0, 0.0],\n", + " [9.1, 4985.0, 12.2, 484.0, 2.7, 125.0, 0.0, 13.9, 6.4, 160.0, 0.0],\n", + " [9.2, 4930.0, 12.4, 439.0, 1.1, 82.0, 0.0, 9.9, 3.0, 66.0, 0.0],\n", + " [24.8, 1829.0, 8.0, 130.0, 0.4, 31.0, 18.9, 2.8, 3.0, 17.0, 0.0],\n", + " [15.1, 3004.0, 12.5, 288.0, 0.5, 50.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", + " [11.0, 8867.0, 6.1, 310.0, 10.5, 18.0, 16.8, 4.0, 16.0, 7.0, 177.0],\n", + " [6.7, 6035.0, 8.4, 422.0, 15.1, 9.0, 26.0, 3.0, 23.5, 11.0, 60.0],\n", + " [20.8, 1473.0, 10.8, 9.0, 0.2, 3.0, 44.2, 0.0, 0.2, 2.0, 0.0],\n", + " [16.1, 2817.0, 20.6, 17.0, 0.6, 6.0, 55.8, 0.2, 0.0, 0.0, 0.0],\n", + " [32.6, 1857.0, 2.9, 238.0, 1.0, 52.0, 18.6, 2.8, 6.5, 1.0, 0.0],\n", + " [24.2, 1874.0, 7.4, 448.0, 16.4, 19.0, 28.1, 0.8, 10.3, 4.0, 0.0],\n", + " [14.1, 1689.0, 3.5, 49.0, 1.7, 3.0, 16.9, 0.6, 2.5, 0.0, 17.0],\n", + " [17.9, 2534.0, 15.7, 661.0, 1.0, 48.0, 0.0, 9.6, 8.1, 471.0, 0.0],\n", + " [16.7, 1198.0, 8.6, 18.0, 0.2, 8.0, 2.7, 0.4, 0.5, 0.0, 0.0],\n", + " [20.3, 2234.0, 20.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", + " [9.8, 4628.0, 41.7, 0.0, 0.0, 0.0, 0.2, 0.0, 0.5, 5.0, 0.0],\n", + " [39.6, 1145.0, 2.9, 166.0, 0.1, 34.0, 0.2, 2.1, 2.9, 69.0, 0.0],\n", + " [36.4, 1246.0, 2.2, 214.0, 0.1, 32.0, 0.4, 2.5, 2.4, 87.0, 0.0],\n", + " [29.2, 1553.0, 3.4, 213.0, 0.1, 33.0, 0.0, 0.0, 2.0, 0.0, 0.0],\n", + " [22.6, 2007.0, 3.6, 309.0, 0.2, 46.0, 0.4, 1.0, 4.0, 120.0, 0.0],\n", + " [14.6, 3107.0, 8.5, 404.0, 0.2, 62.0, 0.0, 0.9, 0.0, 0.0, 0.0],\n", + " [26.8, 1692.0, 2.2, 333.0, 0.2, 139.0, 169.2, 6.4, 50.8, 316.0, 525.0],\n", + " [27.6, 1643.0, 3.1, 245.0, 0.1, 20.0, 0.0, 2.8, 3.0, 86.0, 0.0],\n", + " [36.6, 1239.0, 3.3, 140.0, 0.1, 15.0, 0.0, 1.7, 2.7, 54.0, 0.0],\n", + " [30.7, 1477.0, 3.5, 196.0, 0.2, 80.0, 0.0, 17.4, 2.7, 60.0, 0.0],\n", + " [24.2, 1874.0, 4.4, 249.0, 0.3, 37.0, 0.0, 18.2, 3.6, 79.0, 0.0],\n", + " [25.6, 1772.0, 10.4, 152.0, 0.2, 23.0, 0.0, 1.8, 1.8, 71.0, 0.0],\n", + " [27.4, 1655.0, 6.7, 212.0, 0.2, 31.0, 0.0, 9.9, 3.3, 50.0, 0.0],\n", + " [16.0, 2835.0, 18.8, 164.0, 0.1, 26.0, 0.0, 1.4, 1.8, 0.0, 0.0],\n", + " [30.3, 1497.0, 1.8, 184.0, 0.1, 30.0, 0.1, 0.9, 1.8, 68.0, 46.0],\n", + " [42.3, 1072.0, 1.7, 156.0, 0.1, 24.0, 0.0, 1.4, 2.4, 57.0, 0.0],\n", + " [13.0, 3489.0, 5.8, 705.0, 6.8, 45.0, 3.5, 1.0, 4.9, 209.0, 0.0],\n", + " [4.4, 9072.0, 5.8, 27.0, 0.5, 36.0, 7.3, 3.6, 2.7, 5.0, 544.0],\n", + " [6.1, 4982.0, 4.9, 60.0, 0.4, 30.0, 17.4, 2.5, 3.5, 28.0, 498.0],\n", + " [26.0, 2380.0, 1.0, 21.0, 0.5, 14.0, 0.0, 0.5, 0.0, 4.0, 952.0],\n", + " [30.9, 4439.0, 2.2, 40.0, 1.1, 18.0, 11.1, 3.6, 1.3, 10.0, 1993.0],\n", + " [7.1, 5750.0, 2.4, 138.0, 3.7, 80.0, 69.0, 4.3, 5.8, 37.0, 862.0],\n", + " [3.7, 8949.0, 2.6, 125.0, 4.0, 36.0, 7.2, 9.0, 4.5, 26.0, 5369.0],\n", + " [4.7, 6080.0, 2.7, 73.0, 2.8, 43.0, 188.5, 6.1, 4.3, 89.0, 608.0],\n", + " [7.3, 3915.0, 0.9, 51.0, 3.0, 23.0, 0.9, 1.4, 1.4, 9.0, 313.0],\n", + " [8.2, 2247.0, 0.4, 27.0, 1.1, 22.0, 112.4, 1.8, 3.4, 11.0, 449.0],\n", + " [3.6, 11844.0, 5.8, 166.0, 3.8, 59.0, 16.6, 4.7, 5.9, 21.0, 1184.0],\n", + " [34.0, 16810.0, 14.3, 336.0, 1.8, 118.0, 6.7, 29.4, 7.1, 198.0, 2522.0],\n", + " [8.1, 4592.0, 1.1, 106.0, 0.0, 138.0, 918.4, 5.7, 13.8, 33.0, 2755.0],\n", + " [5.1, 7649.0, 9.6, 138.0, 2.7, 54.0, 290.7, 8.4, 5.4, 83.0, 1912.0],\n", + " [16.8, 4894.0, 3.7, 20.0, 0.4, 10.0, 21.5, 0.5, 1.0, 31.0, 196.0],\n", + " [20.4, 4030.0, 3.0, 8.0, 0.3, 8.0, 0.8, 0.8, 0.8, 5.0, 81.0],\n", + " [21.3, 3993.0, 2.4, 16.0, 0.4, 8.0, 2.0, 2.8, 0.8, 7.0, 399.0],\n", + " [27.7, 1945.0, 0.4, 33.0, 0.3, 12.0, 16.3, 1.4, 2.1, 17.0, 272.0],\n", + " [10.0, 5386.0, 1.0, 54.0, 2.0, 65.0, 53.9, 1.6, 4.3, 32.0, 431.0],\n", + " [7.1, 6389.0, 7.5, 364.0, 4.0, 134.0, 3.5, 8.3, 7.7, 56.0, 0.0],\n", + " [10.4, 5452.0, 5.2, 136.0, 0.2, 16.0, 12.0, 1.6, 2.7, 42.0, 218.0],\n", + " [13.8, 4109.0, 2.3, 136.0, 0.6, 45.0, 34.9, 4.9, 2.5, 37.0, 370.0],\n", + " [8.6, 6263.0, 1.3, 63.0, 0.7, 38.0, 53.2, 3.4, 2.5, 36.0, 1253.0],\n", + " [7.6, 3917.0, 1.6, 71.0, 0.6, 43.0, 57.9, 3.5, 2.4, 67.0, 862.0],\n", + " [15.7, 2889.0, 8.5, 87.0, 1.7, 173.0, 86.8, 1.2, 4.3, 55.0, 57.0],\n", + " [9.0, 4284.0, 12.8, 99.0, 2.5, 154.0, 85.7, 3.9, 4.3, 65.0, 257.0],\n", + " [9.4, 4524.0, 13.5, 104.0, 2.5, 136.0, 4.5, 6.3, 1.4, 24.0, 136.0],\n", + " [7.9, 5742.0, 20.0, 1367.0, 4.2, 345.0, 2.9, 28.7, 18.4, 162.0, 0.0],\n", + " [8.9, 5097.0, 17.4, 1055.0, 3.7, 459.0, 5.1, 26.9, 38.2, 93.0, 0.0],\n", + " [5.9, 7688.0, 26.9, 1691.0, 11.4, 792.0, 0.0, 38.4, 24.6, 217.0, 0.0],\n", + " [22.4, 2025.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.0, 5.1, 50.0, 0.0],\n", + " [17.4, 652.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.3, 42.0, 0.0],\n", + " [8.6, 2637.0, 8.7, 237.0, 3.0, 72.0, 0.0, 2.0, 11.9, 40.0, 0.0],\n", + " [16.2, 1400.0, 8.0, 77.0, 1.3, 39.0, 0.0, 0.9, 3.4, 14.0, 0.0],\n", + " [51.7, 8773.0, 34.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],\n", + " [13.7, 4996.0, 14.7, 0.0, 0.5, 74.0, 0.0, 0.0, 0.0, 5.0, 0.0],\n", + " [13.6, 3752.0, 9.0, 0.0, 10.3, 244.0, 0.0, 1.9, 7.5, 146.0, 0.0],\n", + " [20.5, 2213.0, 6.4, 11.0, 0.4, 7.0, 0.2, 0.2, 0.4, 3.0, 0.0]\n", + " ]\n", "\n", - "# recommended daily allowance for a moderately active man\n", - "allowance = [3.0, 70.0, 0.8, 12.0, 5.0, 1.8, 2.7, 18.0, 75.0]\n", + " # recommended daily allowance for a moderately active man\n", + " allowance = [3.0, 70.0, 0.8, 12.0, 5.0, 1.8, 2.7, 18.0, 75.0]\n", "\n", - "#\n", - "# variables\n", - "#\n", - "x = [solver.NumVar(0, 1000, \"x[%i]\" % i) for i in C]\n", - "x_cost = [solver.NumVar(0, 1000, \"x_cost[%i]\" % i) for i in C]\n", - "quant = [solver.NumVar(0, 1000, \"quant[%i]\" % i) for i in C]\n", + " #\n", + " # variables\n", + " #\n", + " x = [solver.NumVar(0, 1000, \"x[%i]\" % i) for i in C]\n", + " x_cost = [solver.NumVar(0, 1000, \"x_cost[%i]\" % i) for i in C]\n", + " quant = [solver.NumVar(0, 1000, \"quant[%i]\" % i) for i in C]\n", "\n", - "# total food bill\n", - "total_cost = solver.NumVar(0, 1000, \"total_cost\")\n", + " # total food bill\n", + " total_cost = solver.NumVar(0, 1000, \"total_cost\")\n", "\n", - "# cost per day, to minimize\n", - "cost = solver.Sum(x)\n", + " # cost per day, to minimize\n", + " cost = solver.Sum(x)\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(total_cost == days * cost) # cost per year\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(total_cost == days * cost) # cost per year\n", "\n", - "for c in C:\n", - " solver.Add(x_cost[c] == days * x[c])\n", - " solver.Add(quant[c] == 100.0 * days * x[c] / data[c][0])\n", + " for c in C:\n", + " solver.Add(x_cost[c] == days * x[c])\n", + " solver.Add(quant[c] == 100.0 * days * x[c] / data[c][0])\n", "\n", - "# nutrient balance\n", - "for n in range(2, num_nutrients + 2):\n", - " solver.Add(solver.Sum([data[c][n] * x[c] for c in C]) >= allowance[n - 2])\n", + " # nutrient balance\n", + " for n in range(2, num_nutrients + 2):\n", + " solver.Add(solver.Sum([data[c][n] * x[c] for c in C]) >= allowance[n - 2])\n", "\n", - "objective = solver.Minimize(cost)\n", + " objective = solver.Minimize(cost)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\n", + " print()\n", "\n", - "print(\"Cost = %0.2f\" % solver.Objective().Value())\n", - "# print 'Cost:', cost.SolutionValue()\n", - "print(\"Total cost: %0.2f\" % total_cost.SolutionValue())\n", - "print()\n", - "for i in C:\n", - " if x[i].SolutionValue() > 0:\n", - " print(\"%-21s %-11s %0.2f %0.2f\" %\n", - " (commodities[i][0], commodities[i][1], x_cost[i].SolutionValue(),\n", - " quant[i].SolutionValue()))\n", + " print(\"Cost = %0.2f\" % solver.Objective().Value())\n", + " # print 'Cost:', cost.SolutionValue()\n", + " print(\"Total cost: %0.2f\" % total_cost.SolutionValue())\n", + " print()\n", + " for i in C:\n", + " if x[i].SolutionValue() > 0:\n", + " print(\"%-21s %-11s %0.2f %0.2f\" %\n", + " (commodities[i][0], commodities[i][1], x_cost[i].SolutionValue(),\n", + " quant[i].SolutionValue()))\n", "\n", - "print()\n", + " print()\n", "\n", - "print(\"walltime :\", solver.WallTime(), \"ms\")\n", - "if sol == \"CBC\":\n", - " print(\"iterations:\", solver.Iterations())\n", + " print(\"walltime :\", solver.WallTime(), \"ms\")\n", + " if sol == \"CBC\":\n", + " print(\"iterations:\", solver.Iterations())\n", + "\n", + "\n", + "sol = \"CBC\"\n", + "\n", + "if len(sys.argv) > 1:\n", + " sol = sys.argv[1]\n", + " if sol != \"GLPK\" and sol != \"CBC\":\n", + " print(\"Solver must be either GLPK or CBC\")\n", + " sys.exit(1)\n", + "\n", + "main(sol)\n", "\n" ] } diff --git a/examples/notebook/contrib/strimko2.ipynb b/examples/notebook/contrib/strimko2.ipynb index 700a687787..d526712333 100644 --- a/examples/notebook/contrib/strimko2.ipynb +++ b/examples/notebook/contrib/strimko2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", - "\"\"\"Strimko problem in Google CP Solver.\n", + "Strimko problem in Google CP Solver.\n", "\n", " From\n", " 360: A New Twist on Latin Squares\n", @@ -116,96 +101,113 @@ " * Gecode: http://hakank.org/gecode/strimko2.cpp\n", "\n", " This model was created by Hakan Kjellerstrand (hakank@gmail.com)\n", - " See my other Google CP Solver models: http://www.hakank.org/google_or_tools/\n", - "\"\"\"\n", + " See my other Google CP Solver models: http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(streams='', placed=''):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Strimko')\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Strimko')\n", "\n", - "#\n", - "# default problem\n", - "#\n", - "if streams == '':\n", - " streams = [[1, 1, 2, 2, 2, 2, 2], [1, 1, 2, 3, 3, 3, 2],\n", - " [1, 4, 1, 3, 3, 5, 5], [4, 4, 3, 1, 3, 5, 5],\n", - " [4, 6, 6, 6, 7, 7, 5], [6, 4, 6, 4, 5, 5, 7],\n", - " [6, 6, 4, 7, 7, 7, 7]]\n", + " #\n", + " # default problem\n", + " #\n", + " if streams == '':\n", + " streams = [[1, 1, 2, 2, 2, 2, 2], [1, 1, 2, 3, 3, 3, 2],\n", + " [1, 4, 1, 3, 3, 5, 5], [4, 4, 3, 1, 3, 5, 5],\n", + " [4, 6, 6, 6, 7, 7, 5], [6, 4, 6, 4, 5, 5, 7],\n", + " [6, 6, 4, 7, 7, 7, 7]]\n", "\n", - " # Note: This is 1-based\n", - " placed = [[2, 1, 1], [2, 3, 7], [2, 5, 6], [2, 7, 4], [3, 2, 7], [3, 6, 1],\n", - " [4, 1, 4], [4, 7, 5], [5, 2, 2], [5, 6, 6]]\n", + " # Note: This is 1-based\n", + " placed = [[2, 1, 1], [2, 3, 7], [2, 5, 6], [2, 7, 4], [3, 2, 7], [3, 6, 1],\n", + " [4, 1, 4], [4, 7, 5], [5, 2, 2], [5, 6, 6]]\n", "\n", - "n = len(streams)\n", - "num_placed = len(placed)\n", + " n = len(streams)\n", + " num_placed = len(placed)\n", "\n", - "print('n:', n)\n", + " print('n:', n)\n", "\n", - "#\n", - "# variables\n", - "#\n", + " #\n", + " # variables\n", + " #\n", "\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, i.e. a Latin Square\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", - "#\n", - "# streams\n", - "#\n", - "for s in range(1, n + 1):\n", - " tmp = [x[i, j] for i in range(n) for j in range(n) if streams[i][j] == s]\n", - " solver.Add(solver.AllDifferent(tmp))\n", - "\n", - "#\n", - "# placed\n", - "#\n", - "for i in range(num_placed):\n", - " # note: also adjust to 0-based\n", - " solver.Add(x[placed[i][0] - 1, placed[i][1] - 1] == placed[i][2])\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", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " print(x[i, j].Value(), end=' ')\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, i.e. a Latin Square\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", + " #\n", + " # streams\n", + " #\n", + " for s in range(1, n + 1):\n", + " tmp = [x[i, j] for i in range(n) for j in range(n) if streams[i][j] == s]\n", + " solver.Add(solver.AllDifferent(tmp))\n", + "\n", + " #\n", + " # placed\n", + " #\n", + " for i in range(num_placed):\n", + " # note: also adjust to 0-based\n", + " solver.Add(x[placed[i][0] - 1, placed[i][1] - 1] == placed[i][2])\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", - " num_solutions += 1\n", + " print('num_solutions:', num_solutions)\n", + " print('failures:', solver.Failures())\n", + " print('branches:', solver.Branches())\n", + " print('WallTime:', solver.WallTime(), 'ms')\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", + "if len(sys.argv) > 1:\n", + " problem_file = sys.argv[1]\n", + " exec(compile(open(problem_file).read(), problem_file, 'exec'))\n", + " main(streams, placed)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/subset_sum.ipynb b/examples/notebook/contrib/subset_sum.ipynb index e640b8630a..4473ca1990 100644 --- a/examples/notebook/contrib/subset_sum.ipynb +++ b/examples/notebook/contrib/subset_sum.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Subset sum problem in Google CP Solver.\n", "\n", @@ -112,8 +97,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", @@ -129,53 +122,59 @@ " return x, ss\n", "\n", "\n", + "def main(coins, total):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"n-queens\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"n-queens\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"coins:\", coins)\n", - "print(\"total:\", total)\n", - "print()\n", - "\n", - "#\n", - "# declare variables\n", - "#\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "x, ss = subset_sum(solver, coins, total)\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x)\n", - "solution.Add(ss)\n", - "\n", - "# db: DecisionBuilder\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(\"ss:\", ss.Value())\n", - " print(\"x: \", [x[i].Value() for i in range(len(x))])\n", + " #\n", + " # data\n", + " #\n", + " print(\"coins:\", coins)\n", + " print(\"total:\", total)\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", + " # declare variables\n", + " #\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + " x, ss = subset_sum(solver, coins, total)\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x)\n", + " solution.Add(ss)\n", + "\n", + " # db: DecisionBuilder\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(\"ss:\", ss.Value())\n", + " print(\"x: \", [x[i].Value() for i in range(len(x))])\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", "coins = [16, 17, 23, 24, 39, 40]\n", - "total = 100\n" + "total = 100\n", + "if len(sys.argv) > 1:\n", + " total = int(sys.argv[1])\n", + "main(coins, total)\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/survo_puzzle.ipynb b/examples/notebook/contrib/survo_puzzle.ipynb index 21b1d55be4..f59e018338 100644 --- a/examples/notebook/contrib/survo_puzzle.ipynb +++ b/examples/notebook/contrib/survo_puzzle.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Survo puzzle Google CP Solver.\n", "\n", @@ -133,93 +118,103 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(r=0, c=0, rowsums=[], colsums=[], game=[]):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Survo puzzle\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Survo puzzle\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "if r == 0:\n", - " r = 3\n", - " c = 4\n", - " rowsums = [30, 18, 30]\n", - " colsums = [27, 16, 10, 25]\n", - " game = [[0, 6, 0, 0], [8, 0, 0, 0], [0, 0, 3, 0]]\n", + " #\n", + " # data\n", + " #\n", + " if r == 0:\n", + " r = 3\n", + " c = 4\n", + " rowsums = [30, 18, 30]\n", + " colsums = [27, 16, 10, 25]\n", + " game = [[0, 6, 0, 0], [8, 0, 0, 0], [0, 0, 3, 0]]\n", "\n", - "print(\"r:\", r, \"c:\", c)\n", + " print(\"r:\", r, \"c:\", c)\n", + "\n", + " # declare variables\n", + " x = {}\n", + " for i in range(r):\n", + " for j in range(c):\n", + " x[(i, j)] = solver.IntVar(1, r * c, \"x %i %i\" % (i, j))\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + "\n", + " #\n", + " # set the clues\n", + " #\n", + " for i in range(r):\n", + " for j in range(c):\n", + " if game[i][j] > 0:\n", + " solver.Add(x[i, j] == game[i][j])\n", + "\n", + " xflat = [x[(i, j)] for i in range(r) for j in range(c)]\n", + " solver.Add(solver.AllDifferent(xflat))\n", + " #\n", + " # calculate rowsums and colsums\n", + " #\n", + " for i in range(r):\n", + " solver.Add(rowsums[i] == solver.Sum([x[i, j] for j in range(c)]))\n", "\n", - "# declare variables\n", - "x = {}\n", - "for i in range(r):\n", " for j in range(c):\n", - " x[(i, j)] = solver.IntVar(1, r * c, \"x %i %i\" % (i, j))\n", + " solver.Add(colsums[j] == solver.Sum([x[i, j] for i in range(r)]))\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add([x[(i, j)] for i in range(r) for j in range(c)])\n", "\n", - "#\n", - "# set the clues\n", - "#\n", - "for i in range(r):\n", - " for j in range(c):\n", - " if game[i][j] > 0:\n", - " solver.Add(x[i, j] == game[i][j])\n", + " collector = solver.AllSolutionCollector(solution)\n", + " solver.Solve(\n", + " solver.Phase(xflat, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n", + " [collector])\n", "\n", - "xflat = [x[(i, j)] for i in range(r) for j in range(c)]\n", - "solver.Add(solver.AllDifferent(xflat))\n", - "#\n", - "# calculate rowsums and colsums\n", - "#\n", - "for i in range(r):\n", - " solver.Add(rowsums[i] == solver.Sum([x[i, j] for j in range(c)]))\n", + " num_solutions = collector.SolutionCount()\n", + " print(\"\\nnum_solutions: \", num_solutions)\n", + " if num_solutions > 0:\n", + " for s in range(num_solutions):\n", + " xval = [collector.Value(s, x[(i, j)]) for i in range(r) for j in range(c)]\n", "\n", - "for j in range(c):\n", - " solver.Add(colsums[j] == solver.Sum([x[i, j] for i in range(r)]))\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add([x[(i, j)] for i in range(r) for j in range(c)])\n", - "\n", - "collector = solver.AllSolutionCollector(solution)\n", - "solver.Solve(\n", - " solver.Phase(xflat, solver.CHOOSE_FIRST_UNBOUND, solver.ASSIGN_MIN_VALUE),\n", - " [collector])\n", - "\n", - "num_solutions = collector.SolutionCount()\n", - "print(\"\\nnum_solutions: \", num_solutions)\n", - "if num_solutions > 0:\n", - " for s in range(num_solutions):\n", - " xval = [collector.Value(s, x[(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(\"%2i\" % (xval[i * c + j]), end=\" \")\n", + " for i in range(r):\n", + " for j in range(c):\n", + " print(\"%2i\" % (xval[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", - " 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", + " else:\n", + " print(\"No solutions found\")\n", "\n", "\n", "#\n", "# Read a problem instance from a file\n", - "#def read_problem(file):\n", + "#\n", + "def read_problem(file):\n", " f = open(file, \"r\")\n", " r = int(f.readline())\n", " c = int(f.readline())\n", @@ -237,6 +232,13 @@ " game.append(row)\n", " return [r, c, rowsums, colsums, game]\n", "\n", + "\n", + "if len(sys.argv) > 1:\n", + " file = sys.argv[1]\n", + " [r, c, rowsums, colsums, game] = read_problem(file)\n", + " main(r, c, rowsums, colsums, game)\n", + "else:\n", + " main()\n", "\n" ] } diff --git a/examples/notebook/contrib/toNum.ipynb b/examples/notebook/contrib/toNum.ipynb index 0741474f7b..dd2ebfaaf1 100644 --- a/examples/notebook/contrib/toNum.ipynb +++ b/examples/notebook/contrib/toNum.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " toNum in Google CP Solver.\n", "\n", @@ -96,8 +81,16 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "#\n", @@ -111,47 +104,51 @@ " s == solver.Sum([(base**(tlen - i - 1)) * t[i] for i in range(tlen)]))\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"toNum test\")\n", + "def main(unused_argv):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"toNum test\")\n", "\n", - "# data\n", - "n = 4\n", - "base = 10\n", + " # data\n", + " n = 4\n", + " base = 10\n", "\n", - "# declare variables\n", - "x = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(n)]\n", - "y = solver.IntVar(0, 10**n - 1, \"y\")\n", + " # declare variables\n", + " x = [solver.IntVar(0, n - 1, \"x%i\" % i) for i in range(n)]\n", + " y = solver.IntVar(0, 10**n - 1, \"y\")\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "# solver.Add(solver.AllDifferent([x[i] for i in range(n)]))\n", - "solver.Add(solver.AllDifferent(x))\n", - "# solver.Add(x[0] > 0) # just for fun\n", + " #\n", + " # constraints\n", + " #\n", + " # solver.Add(solver.AllDifferent([x[i] for i in range(n)]))\n", + " solver.Add(solver.AllDifferent(x))\n", + " # solver.Add(x[0] > 0) # just for fun\n", "\n", - "toNum(solver, x, y, base)\n", + " toNum(solver, x, y, base)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add([x[i] for i in range(n)])\n", - "solution.Add(y)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add([x[i] for i in range(n)])\n", + " solution.Add(y)\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", + " 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(\"y:\", collector.Value(s, y))\n", - " print()\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(\"y:\", collector.Value(s, y))\n", + " print()\n", "\n", - "print(\"failures:\", solver.Failures())\n", - "print(\"branches:\", solver.Branches())\n", - "print(\"WallTime:\", solver.WallTime())\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\n", + "\n", + "\n", + "main(\"cp sample\")\n", "\n" ] } diff --git a/examples/notebook/contrib/traffic_lights.ipynb b/examples/notebook/contrib/traffic_lights.ipynb index b65b3e74fc..ec6cef2243 100644 --- a/examples/notebook/contrib/traffic_lights.ipynb +++ b/examples/notebook/contrib/traffic_lights.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Traffic lights problem in Google CP Solver.\n", "\n", @@ -143,63 +128,75 @@ " 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" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(base=10, start=1, len1=1, len2=4):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Traffic lights\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Traffic lights\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 4\n", - "r, ry, g, y = list(range(n))\n", - "lights = [\"r\", \"ry\", \"g\", \"y\"]\n", + " #\n", + " # data\n", + " #\n", + " n = 4\n", + " r, ry, g, y = list(range(n))\n", + " lights = [\"r\", \"ry\", \"g\", \"y\"]\n", "\n", - "# The allowed combinations\n", - "allowed = []\n", - "allowed.extend([(r, r, g, g), (ry, r, y, r), (g, g, r, r), (y, r, ry, r)])\n", + " # The allowed combinations\n", + " allowed = []\n", + " allowed.extend([(r, r, g, g), (ry, r, y, r), (g, g, r, r), (y, r, ry, r)])\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "V = [solver.IntVar(0, n - 1, \"V[%i]\" % i) for i in range(n)]\n", - "P = [solver.IntVar(0, n - 1, \"P[%i]\" % i) for i in range(n)]\n", + " #\n", + " # declare variables\n", + " #\n", + " V = [solver.IntVar(0, n - 1, \"V[%i]\" % i) for i in range(n)]\n", + " P = [solver.IntVar(0, n - 1, \"P[%i]\" % i) for i in range(n)]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if j == (1 + i) % n:\n", - " solver.Add(solver.AllowedAssignments((V[i], P[i], V[j], P[j]), allowed))\n", - "\n", - "#\n", - "# Search and result\n", - "#\n", - "db = solver.Phase(V + P, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", - "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", + " #\n", + " # constraints\n", + " #\n", " for i in range(n):\n", - " print(\"%+2s %+2s\" % (lights[V[i].Value()], lights[P[i].Value()]), end=\" \")\n", + " for j in range(n):\n", + " if j == (1 + i) % n:\n", + " solver.Add(solver.AllowedAssignments((V[i], P[i], V[j], P[j]), allowed))\n", + "\n", + " #\n", + " # Search and result\n", + " #\n", + " db = solver.Phase(V + P, solver.INT_VAR_SIMPLE, solver.INT_VALUE_DEFAULT)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " for i in range(n):\n", + " print(\"%+2s %+2s\" % (lights[V[i].Value()], lights[P[i].Value()]), end=\" \")\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", " 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", - "print()\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/vendor_scheduling.ipynb b/examples/notebook/contrib/vendor_scheduling.ipynb index 810fa9cc31..555fbe89f5 100644 --- a/examples/notebook/contrib/vendor_scheduling.ipynb +++ b/examples/notebook/contrib/vendor_scheduling.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -77,98 +77,102 @@ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('Vendors scheduling')\n", + "def main():\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('Vendors scheduling')\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_vendors = 9\n", - "num_hours = 10\n", - "num_work_types = 1\n", + " #\n", + " # data\n", + " #\n", + " num_vendors = 9\n", + " num_hours = 10\n", + " num_work_types = 1\n", "\n", - "trafic = [100, 500, 100, 200, 320, 300, 200, 220, 300, 120]\n", - "max_trafic_per_vendor = 100\n", + " trafic = [100, 500, 100, 200, 320, 300, 200, 220, 300, 120]\n", + " max_trafic_per_vendor = 100\n", "\n", - "# Last columns are :\n", - "# index_of_the_schedule, sum of worked hours (per work type).\n", - "# The index is useful for branching.\n", - "possible_schedules = [[1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 8],\n", - " [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 4],\n", - " [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 2, 5],\n", - " [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 4],\n", - " [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 4, 3],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0]]\n", + " # Last columns are :\n", + " # index_of_the_schedule, sum of worked hours (per work type).\n", + " # The index is useful for branching.\n", + " possible_schedules = [[1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 8],\n", + " [1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 4],\n", + " [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 2, 5],\n", + " [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 4],\n", + " [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 4, 3],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0]]\n", "\n", - "num_possible_schedules = len(possible_schedules)\n", - "selected_schedules = []\n", - "vendors_stat = []\n", - "hours_stat = []\n", + " num_possible_schedules = len(possible_schedules)\n", + " selected_schedules = []\n", + " vendors_stat = []\n", + " hours_stat = []\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "x = {}\n", - "\n", - "for i in range(num_vendors):\n", - " tmp = []\n", - " for j in range(num_hours):\n", - " x[i, j] = solver.IntVar(0, num_work_types, 'x[%i,%i]' % (i, j))\n", - " tmp.append(x[i, j])\n", - " selected_schedule = solver.IntVar(0, num_possible_schedules - 1,\n", - " 's[%i]' % i)\n", - " hours = solver.IntVar(0, num_hours, 'h[%i]' % i)\n", - " selected_schedules.append(selected_schedule)\n", - " vendors_stat.append(hours)\n", - " tmp.append(selected_schedule)\n", - " tmp.append(hours)\n", - "\n", - " solver.Add(solver.AllowedAssignments(tmp, possible_schedules))\n", - "\n", - "#\n", - "# Statistics and constraints for each hour\n", - "#\n", - "for j in range(num_hours):\n", - " workers = solver.Sum([x[i, j] for i in range(num_vendors)]).Var()\n", - " hours_stat.append(workers)\n", - " solver.Add(workers * max_trafic_per_vendor >= trafic[j])\n", - "\n", - "#\n", - "# Redundant constraint: sort selected_schedules\n", - "#\n", - "for i in range(num_vendors - 1):\n", - " solver.Add(selected_schedules[i] <= selected_schedules[i + 1])\n", - "\n", - "#\n", - "# Search\n", - "#\n", - "db = solver.Phase(selected_schedules, 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", + " #\n", + " # declare variables\n", + " #\n", + " x = {}\n", "\n", " for i in range(num_vendors):\n", - " print('Vendor %i: ' % i,\n", - " possible_schedules[selected_schedules[i].Value()])\n", - " print()\n", + " tmp = []\n", + " for j in range(num_hours):\n", + " x[i, j] = solver.IntVar(0, num_work_types, 'x[%i,%i]' % (i, j))\n", + " tmp.append(x[i, j])\n", + " selected_schedule = solver.IntVar(0, num_possible_schedules - 1,\n", + " 's[%i]' % i)\n", + " hours = solver.IntVar(0, num_hours, 'h[%i]' % i)\n", + " selected_schedules.append(selected_schedule)\n", + " vendors_stat.append(hours)\n", + " tmp.append(selected_schedule)\n", + " tmp.append(hours)\n", "\n", - " print('Statistics per day:')\n", + " solver.Add(solver.AllowedAssignments(tmp, possible_schedules))\n", + "\n", + " #\n", + " # Statistics and constraints for each hour\n", + " #\n", " for j in range(num_hours):\n", - " print('Day%2i: ' % j, end=' ')\n", - " print(hours_stat[j].Value(), end=' ')\n", - " print()\n", - " print()\n", + " workers = solver.Sum([x[i, j] for i in range(num_vendors)]).Var()\n", + " hours_stat.append(workers)\n", + " solver.Add(workers * max_trafic_per_vendor >= trafic[j])\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", + " # Redundant constraint: sort selected_schedules\n", + " #\n", + " for i in range(num_vendors - 1):\n", + " solver.Add(selected_schedules[i] <= selected_schedules[i + 1])\n", + "\n", + " #\n", + " # Search\n", + " #\n", + " db = solver.Phase(selected_schedules, 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", + "\n", + " for i in range(num_vendors):\n", + " print('Vendor %i: ' % i,\n", + " possible_schedules[selected_schedules[i].Value()])\n", + " print()\n", + "\n", + " print('Statistics per day:')\n", + " for j in range(num_hours):\n", + " print('Day%2i: ' % j, end=' ')\n", + " print(hours_stat[j].Value(), end=' ')\n", + " print()\n", + " print()\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/volsay.ipynb b/examples/notebook/contrib/volsay.ipynb index d1225db78e..0cac7535b9 100644 --- a/examples/notebook/contrib/volsay.ipynb +++ b/examples/notebook/contrib/volsay.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Volsay problem in Google or-tools.\n", "\n", @@ -95,49 +80,61 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "# using GLPK\n", - "#solver = pywraplp.Solver('CoinsGridGLPK',\n", - "# pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", + " # using GLPK\n", + " #solver = pywraplp.Solver('CoinsGridGLPK',\n", + " # pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", "\n", - "# Using CLP\n", - "solver = pywraplp.Solver('CoinsGridCLP',\n", - " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", + " # Using CLP\n", + " solver = pywraplp.Solver('CoinsGridCLP',\n", + " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", "\n", - "# data\n", + " # data\n", "\n", - "# declare variables\n", - "Gas = solver.NumVar(0, 100000, 'Gas')\n", - "Chloride = solver.NumVar(0, 100000, 'Cloride')\n", + " # declare variables\n", + " Gas = solver.NumVar(0, 100000, 'Gas')\n", + " Chloride = solver.NumVar(0, 100000, 'Cloride')\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(Gas + Chloride <= 50)\n", - "solver.Add(3 * Gas + 4 * Chloride <= 180)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(Gas + Chloride <= 50)\n", + " solver.Add(3 * Gas + 4 * Chloride <= 180)\n", "\n", - "# objective\n", - "objective = solver.Maximize(40 * Gas + 50 * Chloride)\n", + " # objective\n", + " objective = solver.Maximize(40 * Gas + 50 * Chloride)\n", "\n", - "print('NumConstraints:', solver.NumConstraints())\n", + " print('NumConstraints:', solver.NumConstraints())\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\n", - "print('objective = ', solver.Objective().Value())\n", - "print('Gas = ', Gas.SolutionValue(), 'ReducedCost =', Gas.ReducedCost())\n", - "print('Chloride:', Chloride.SolutionValue(), 'ReducedCost =',\n", - " Chloride.ReducedCost())\n", + " print()\n", + " print('objective = ', solver.Objective().Value())\n", + " print('Gas = ', Gas.SolutionValue(), 'ReducedCost =', Gas.ReducedCost())\n", + " print('Chloride:', Chloride.SolutionValue(), 'ReducedCost =',\n", + " Chloride.ReducedCost())\n", + "\n", + "\n", + "main('Volsay')\n", "\n" ] } diff --git a/examples/notebook/contrib/volsay2.ipynb b/examples/notebook/contrib/volsay2.ipynb index 5b69eb91f0..0f5c315bff 100644 --- a/examples/notebook/contrib/volsay2.ipynb +++ b/examples/notebook/contrib/volsay2.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Volsay problem in Google or-tools.\n", "\n", @@ -96,56 +81,68 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "# using GLPK\n", - "# solver = pywraplp.Solver('CoinsGridGLPK',\n", - "# pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", + " # using GLPK\n", + " # solver = pywraplp.Solver('CoinsGridGLPK',\n", + " # pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", "\n", - "# Using CLP\n", - "solver = pywraplp.Solver('CoinsGridCLP',\n", - " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", + " # Using CLP\n", + " solver = pywraplp.Solver('CoinsGridCLP',\n", + " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", "\n", - "# data\n", - "num_products = 2\n", - "Gas = 0\n", - "Chloride = 1\n", + " # data\n", + " num_products = 2\n", + " Gas = 0\n", + " Chloride = 1\n", "\n", - "products = ['Gas', 'Chloride']\n", + " products = ['Gas', 'Chloride']\n", "\n", - "# declare variables\n", - "production = [\n", - " solver.NumVar(0, 100000, 'production[%i]' % i)\n", - " for i in range(num_products)\n", - "]\n", + " # declare variables\n", + " production = [\n", + " solver.NumVar(0, 100000, 'production[%i]' % i)\n", + " for i in range(num_products)\n", + " ]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(production[Gas] + production[Chloride] <= 50)\n", - "solver.Add(3 * production[Gas] + 4 * production[Chloride] <= 180)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(production[Gas] + production[Chloride] <= 50)\n", + " solver.Add(3 * production[Gas] + 4 * production[Chloride] <= 180)\n", "\n", - "# objective\n", - "objective = solver.Maximize(40 * production[Gas] + 50 * production[Chloride])\n", + " # objective\n", + " objective = solver.Maximize(40 * production[Gas] + 50 * production[Chloride])\n", "\n", - "print('NumConstraints:', solver.NumConstraints())\n", + " print('NumConstraints:', solver.NumConstraints())\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\n", - "print('objective = ', solver.Objective().Value())\n", - "for i in range(num_products):\n", - " print(products[i], '=', production[i].SolutionValue(), end=' ')\n", - " print('ReducedCost = ', production[i].ReducedCost())\n", + " print()\n", + " print('objective = ', solver.Objective().Value())\n", + " for i in range(num_products):\n", + " print(products[i], '=', production[i].SolutionValue(), end=' ')\n", + " print('ReducedCost = ', production[i].ReducedCost())\n", + "\n", + "\n", + "main('Volsay')\n", "\n" ] } diff --git a/examples/notebook/contrib/volsay3.ipynb b/examples/notebook/contrib/volsay3.ipynb index 1cdd39324f..32547c283f 100644 --- a/examples/notebook/contrib/volsay3.ipynb +++ b/examples/notebook/contrib/volsay3.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", "\n", " Volsay problem in Google or-tools.\n", "\n", @@ -96,69 +81,81 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.linear_solver import pywraplp\n", "\n", "\n", + "def main(unused_argv):\n", "\n", - "# Create the solver.\n", + " # Create the solver.\n", "\n", - "# using GLPK\n", - "# solver = pywraplp.Solver('CoinsGridGLPK',\n", - "# pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", + " # using GLPK\n", + " # solver = pywraplp.Solver('CoinsGridGLPK',\n", + " # pywraplp.Solver.GLPK_LINEAR_PROGRAMMING)\n", "\n", - "# Using CLP\n", - "solver = pywraplp.Solver('CoinsGridCLP',\n", - " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", + " # Using CLP\n", + " solver = pywraplp.Solver('CoinsGridCLP',\n", + " pywraplp.Solver.CLP_LINEAR_PROGRAMMING)\n", "\n", - "# data\n", - "num_products = 2\n", + " # data\n", + " num_products = 2\n", "\n", - "products = ['Gas', 'Chloride']\n", - "components = ['nitrogen', 'hydrogen', 'chlorine']\n", + " products = ['Gas', 'Chloride']\n", + " components = ['nitrogen', 'hydrogen', 'chlorine']\n", "\n", - "demand = [[1, 3, 0], [1, 4, 1]]\n", - "profit = [30, 40]\n", - "stock = [50, 180, 40]\n", + " demand = [[1, 3, 0], [1, 4, 1]]\n", + " profit = [30, 40]\n", + " stock = [50, 180, 40]\n", "\n", - "# declare variables\n", - "production = [\n", - " solver.NumVar(0, 100000, 'production[%i]' % i)\n", - " for i in range(num_products)\n", - "]\n", + " # declare variables\n", + " production = [\n", + " solver.NumVar(0, 100000, 'production[%i]' % i)\n", + " for i in range(num_products)\n", + " ]\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "for c in range(len(components)):\n", - " solver.Add(\n", - " solver.Sum([demand[p][c] * production[p]\n", - " for p in range(len(products))]) <= stock[c])\n", + " #\n", + " # constraints\n", + " #\n", + " for c in range(len(components)):\n", + " solver.Add(\n", + " solver.Sum([demand[p][c] * production[p]\n", + " for p in range(len(products))]) <= stock[c])\n", "\n", - "# objective\n", - "# Note: there is no support for solver.ScalProd in the LP/IP interface\n", - "objective = solver.Maximize(\n", - " solver.Sum([production[p] * profit[p] for p in range(num_products)]))\n", + " # objective\n", + " # Note: there is no support for solver.ScalProd in the LP/IP interface\n", + " objective = solver.Maximize(\n", + " solver.Sum([production[p] * profit[p] for p in range(num_products)]))\n", "\n", - "print('NumConstraints:', solver.NumConstraints())\n", - "print('NumVariables:', solver.NumVariables())\n", - "print()\n", + " print('NumConstraints:', solver.NumConstraints())\n", + " print('NumVariables:', solver.NumVariables())\n", + " print()\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solver.Solve()\n", + " #\n", + " # solution and search\n", + " #\n", + " solver.Solve()\n", "\n", - "print()\n", - "print('objective = ', solver.Objective().Value())\n", - "for i in range(num_products):\n", - " print(products[i], '=', production[i].SolutionValue(), end=' ')\n", - " print('ReducedCost = ', production[i].ReducedCost())\n", + " print()\n", + " print('objective = ', solver.Objective().Value())\n", + " for i in range(num_products):\n", + " print(products[i], '=', production[i].SolutionValue(), end=' ')\n", + " print('ReducedCost = ', production[i].ReducedCost())\n", "\n", - "print()\n", - "print('walltime :', solver.WallTime(), 'ms')\n", - "print('iterations:', solver.Iterations())\n", + " print()\n", + " print('walltime :', solver.WallTime(), 'ms')\n", + " print('iterations:', solver.Iterations())\n", + "\n", + "\n", + "main('Volsay')\n", "\n" ] } diff --git a/examples/notebook/contrib/wedding_optimal_chart.ipynb b/examples/notebook/contrib/wedding_optimal_chart.ipynb index 6a1bba0747..ffe01d105f 100644 --- a/examples/notebook/contrib/wedding_optimal_chart.ipynb +++ b/examples/notebook/contrib/wedding_optimal_chart.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -116,120 +116,124 @@ "\"\"\"\n", "\n", "\n", - "# Instantiate a CP solver.\n", - "parameters = pywrapcp.Solver.DefaultSolverParameters()\n", - "solver = pywrapcp.Solver(\"WeddingOptimalChart\", parameters)\n", + "def main():\n", + " # Instantiate a CP solver.\n", + " parameters = pywrapcp.Solver.DefaultSolverParameters()\n", + " solver = pywrapcp.Solver(\"WeddingOptimalChart\", parameters)\n", "\n", - "#\n", - "# Data\n", - "#\n", + " #\n", + " # Data\n", + " #\n", "\n", - "# Easy problem (from the paper)\n", - "# n = 2 # number of tables\n", - "# a = 10 # maximum number of guests a table can seat\n", - "# b = 1 # minimum number of people each guest knows at their table\n", + " # Easy problem (from the paper)\n", + " # n = 2 # number of tables\n", + " # a = 10 # maximum number of guests a table can seat\n", + " # b = 1 # minimum number of people each guest knows at their table\n", "\n", - "# Slightly harder problem (also from the paper)\n", - "n = 5 # number of tables\n", - "a = 4 # maximum number of guests a table can seat\n", - "b = 1 # minimum number of people each guest knows at their table\n", + " # Slightly harder problem (also from the paper)\n", + " n = 5 # number of tables\n", + " a = 4 # maximum number of guests a table can seat\n", + " b = 1 # minimum number of people each guest knows at their table\n", "\n", - "# Connection matrix: who knows who, and how strong\n", - "# is the relation\n", - "C = [[1, 50, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [50, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 1, 50, 1, 1, 1, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 50, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 1, 1, 1, 50, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 1, 1, 50, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 1, 1, 1, 1, 1, 50, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 1, 1, 1, 1, 50, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [1, 1, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", - " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]]\n", + " # Connection matrix: who knows who, and how strong\n", + " # is the relation\n", + " C = [[1, 50, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [50, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 50, 1, 1, 1, 1, 10, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 50, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 1, 50, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 50, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 1, 1, 1, 50, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 1, 1, 1, 1, 50, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [1, 1, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 50, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1],\n", + " [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]]\n", "\n", - "# Names of the guests. B: Bride side, G: Groom side\n", - "names = [\n", - " \"Deb (B)\", \"John (B)\", \"Martha (B)\", \"Travis (B)\", \"Allan (B)\",\n", - " \"Lois (B)\", \"Jayne (B)\", \"Brad (B)\", \"Abby (B)\", \"Mary Helen (G)\",\n", - " \"Lee (G)\", \"Annika (G)\", \"Carl (G)\", \"Colin (G)\", \"Shirley (G)\",\n", - " \"DeAnn (G)\", \"Lori (G)\"\n", - "]\n", + " # Names of the guests. B: Bride side, G: Groom side\n", + " names = [\n", + " \"Deb (B)\", \"John (B)\", \"Martha (B)\", \"Travis (B)\", \"Allan (B)\",\n", + " \"Lois (B)\", \"Jayne (B)\", \"Brad (B)\", \"Abby (B)\", \"Mary Helen (G)\",\n", + " \"Lee (G)\", \"Annika (G)\", \"Carl (G)\", \"Colin (G)\", \"Shirley (G)\",\n", + " \"DeAnn (G)\", \"Lori (G)\"\n", + " ]\n", "\n", - "m = len(C)\n", + " m = len(C)\n", "\n", - "NRANGE = range(n)\n", - "MRANGE = range(m)\n", + " NRANGE = range(n)\n", + " MRANGE = range(m)\n", "\n", - "#\n", - "# Decision variables\n", - "#\n", - "tables = [solver.IntVar(0, n - 1, \"x[%i]\" % i) for i in MRANGE]\n", + " #\n", + " # Decision variables\n", + " #\n", + " tables = [solver.IntVar(0, n - 1, \"x[%i]\" % i) for i in MRANGE]\n", "\n", - "z = solver.Sum([\n", - " C[j][k] * (tables[j] == tables[k])\n", - " for j in MRANGE\n", - " for k in MRANGE\n", - " if j < k\n", - "])\n", - "\n", - "#\n", - "# Constraints\n", - "#\n", - "for i in NRANGE:\n", - " minGuests = [(tables[j] == i) * (tables[k] == i)\n", - " for j in MRANGE\n", - " for k in MRANGE\n", - " if j < k and C[j][k] > 0]\n", - " solver.Add(solver.Sum(minGuests) >= b)\n", - "\n", - " maxGuests = [tables[j] == i for j in MRANGE]\n", - " solver.Add(solver.Sum(maxGuests) <= a)\n", - "\n", - "# Symmetry breaking\n", - "solver.Add(tables[0] == 0)\n", - "\n", - "#\n", - "# Objective\n", - "#\n", - "objective = solver.Maximize(z, 1)\n", - "\n", - "#\n", - "# Search\n", - "#\n", - "db = solver.Phase(tables, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", - "\n", - "solver.NewSearch(db, [objective])\n", - "\n", - "while solver.NextSolution():\n", - " print(\"z:\", z)\n", - " print(\"Table: \")\n", - " for j in MRANGE:\n", - " print(tables[j].Value(), \" \")\n", - " print()\n", + " z = solver.Sum([\n", + " C[j][k] * (tables[j] == tables[k])\n", + " for j in MRANGE\n", + " for k in MRANGE\n", + " if j < k\n", + " ])\n", "\n", + " #\n", + " # Constraints\n", + " #\n", " for i in NRANGE:\n", - " print(\"Table %d: \" % i)\n", + " minGuests = [(tables[j] == i) * (tables[k] == i)\n", + " for j in MRANGE\n", + " for k in MRANGE\n", + " if j < k and C[j][k] > 0]\n", + " solver.Add(solver.Sum(minGuests) >= b)\n", + "\n", + " maxGuests = [tables[j] == i for j in MRANGE]\n", + " solver.Add(solver.Sum(maxGuests) <= a)\n", + "\n", + " # Symmetry breaking\n", + " solver.Add(tables[0] == 0)\n", + "\n", + " #\n", + " # Objective\n", + " #\n", + " objective = solver.Maximize(z, 1)\n", + "\n", + " #\n", + " # Search\n", + " #\n", + " db = solver.Phase(tables, solver.INT_VAR_DEFAULT, solver.INT_VALUE_DEFAULT)\n", + "\n", + " solver.NewSearch(db, [objective])\n", + "\n", + " while solver.NextSolution():\n", + " print(\"z:\", z)\n", + " print(\"Table: \")\n", " for j in MRANGE:\n", - " if tables[j].Value() == i:\n", - " print(names[j] + \" \")\n", + " print(tables[j].Value(), \" \")\n", " print()\n", "\n", + " for i in NRANGE:\n", + " print(\"Table %d: \" % i)\n", + " for j in MRANGE:\n", + " if tables[j].Value() == i:\n", + " print(names[j] + \" \")\n", + " print()\n", + "\n", + " print()\n", + "\n", + " solver.EndSearch()\n", + "\n", " print()\n", + " print(\"Solutions: %d\" % solver.Solutions())\n", + " print(\"WallTime: %dms\" % solver.WallTime())\n", + " print(\"Failures: %d\" % solver.Failures())\n", + " print(\"Branches: %d\" % solver.Branches())\n", "\n", - "solver.EndSearch()\n", "\n", - "print()\n", - "print(\"Solutions: %d\" % solver.Solutions())\n", - "print(\"WallTime: %dms\" % solver.WallTime())\n", - "print(\"Failures: %d\" % solver.Failures())\n", - "print(\"Branches: %d\" % solver.Branches())\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/who_killed_agatha.ipynb b/examples/notebook/contrib/who_killed_agatha.ipynb index 9cafce584c..ba4ee50b00 100644 --- a/examples/notebook/contrib/who_killed_agatha.ipynb +++ b/examples/notebook/contrib/who_killed_agatha.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Who killed agatha? (The Dreadsbury Mansion Murder Mystery) in Google CP\n", " Solver.\n", @@ -133,8 +118,16 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from collections import defaultdict\n", "\n", "from ortools.constraint_solver import pywrapcp\n", @@ -162,123 +155,131 @@ " print()\n", "\n", "\n", + "def main(the_killers):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Who killed agatha?\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Who killed agatha?\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "n = 3\n", - "agatha = 0\n", - "butler = 1\n", - "charles = 2\n", + " #\n", + " # data\n", + " #\n", + " n = 3\n", + " agatha = 0\n", + " butler = 1\n", + " charles = 2\n", "\n", - "#\n", - "# declare variables\n", - "#\n", - "the_killer = solver.IntVar(0, 2, \"the_killer\")\n", - "the_victim = solver.IntVar(0, 2, \"the_victim\")\n", + " #\n", + " # declare variables\n", + " #\n", + " the_killer = solver.IntVar(0, 2, \"the_killer\")\n", + " the_victim = solver.IntVar(0, 2, \"the_victim\")\n", "\n", - "hates = var_matrix_array(solver, n, n, 0, 1, \"hates\")\n", - "richer = var_matrix_array(solver, n, n, 0, 1, \"richer\")\n", + " hates = var_matrix_array(solver, n, n, 0, 1, \"hates\")\n", + " richer = var_matrix_array(solver, n, n, 0, 1, \"richer\")\n", "\n", - "hates_flat = flatten_matrix(solver, hates, n, n)\n", - "richer_flat = flatten_matrix(solver, richer, n, n)\n", + " hates_flat = flatten_matrix(solver, hates, n, n)\n", + " richer_flat = flatten_matrix(solver, richer, n, n)\n", "\n", - "#\n", - "# constraints\n", - "#\n", + " #\n", + " # constraints\n", + " #\n", "\n", - "# Agatha, the butler, and Charles live in Dreadsbury Mansion, and\n", - "# are the only ones to live there.\n", + " # Agatha, the butler, and Charles live in Dreadsbury Mansion, and\n", + " # are the only ones to live there.\n", "\n", - "# A killer always hates, and is no richer than his victim.\n", - "# solver.Add(hates[the_killer, the_victim] == 1)\n", - "solver.Add(solver.Element(hates_flat, the_killer * n + the_victim) == 1)\n", + " # A killer always hates, and is no richer than his victim.\n", + " # solver.Add(hates[the_killer, the_victim] == 1)\n", + " solver.Add(solver.Element(hates_flat, the_killer * n + the_victim) == 1)\n", "\n", - "# solver.Add(richer[the_killer, the_victim] == 0)\n", - "solver.Add(solver.Element(richer_flat, the_killer * n + the_victim) == 0)\n", + " # solver.Add(richer[the_killer, the_victim] == 0)\n", + " solver.Add(solver.Element(richer_flat, the_killer * n + the_victim) == 0)\n", "\n", - "# define the concept of richer: no one is richer than him-/herself\n", - "for i in range(n):\n", - " solver.Add(richer[i][i] == 0)\n", + " # define the concept of richer: no one is richer than him-/herself\n", + " for i in range(n):\n", + " solver.Add(richer[i][i] == 0)\n", "\n", - "# (contd...) if i is richer than j then j is not richer than i\n", - "# (i != j) => (richer[i,j] = 1) <=> (richer[j,i] = 0),\n", - "for i in range(n):\n", - " for j in range(n):\n", - " if i != j:\n", - " solver.Add((richer[i][j] == 1) == (richer[j][i] == 0))\n", + " # (contd...) if i is richer than j then j is not richer than i\n", + " # (i != j) => (richer[i,j] = 1) <=> (richer[j,i] = 0),\n", + " for i in range(n):\n", + " for j in range(n):\n", + " if i != j:\n", + " solver.Add((richer[i][j] == 1) == (richer[j][i] == 0))\n", "\n", - "# Charles hates noone that Agatha hates.\n", - "# forall i : Range .\n", - "# (hates[agatha, i] = 1) => (hates[charles, i] = 0),\n", - "for i in range(n):\n", - " solver.Add((hates[agatha][i] == 1) <= (hates[charles][i] == 0))\n", + " # Charles hates noone that Agatha hates.\n", + " # forall i : Range .\n", + " # (hates[agatha, i] = 1) => (hates[charles, i] = 0),\n", + " for i in range(n):\n", + " solver.Add((hates[agatha][i] == 1) <= (hates[charles][i] == 0))\n", "\n", - "# Agatha hates everybody except the butler.\n", - "solver.Add(hates[agatha][charles] == 1)\n", - "solver.Add(hates[agatha][agatha] == 1)\n", - "solver.Add(hates[agatha][butler] == 0)\n", + " # Agatha hates everybody except the butler.\n", + " solver.Add(hates[agatha][charles] == 1)\n", + " solver.Add(hates[agatha][agatha] == 1)\n", + " solver.Add(hates[agatha][butler] == 0)\n", "\n", - "# The butler hates everyone not richer than Aunt Agatha.\n", - "# forall i : Range .\n", - "# (richer[i, agatha] = 0) => (hates[butler, i] = 1),\n", - "for i in range(n):\n", - " solver.Add((richer[i][agatha] == 0) <= (hates[butler][i] == 1))\n", + " # The butler hates everyone not richer than Aunt Agatha.\n", + " # forall i : Range .\n", + " # (richer[i, agatha] = 0) => (hates[butler, i] = 1),\n", + " for i in range(n):\n", + " solver.Add((richer[i][agatha] == 0) <= (hates[butler][i] == 1))\n", "\n", - "# The butler hates everyone whom Agatha hates.\n", - "# forall i : Range .\n", - "# (hates[agatha, i] = 1) => (hates[butler, i] = 1),\n", - "for i in range(n):\n", - " solver.Add((hates[agatha][i] == 1) <= (hates[butler][i] == 1))\n", + " # The butler hates everyone whom Agatha hates.\n", + " # forall i : Range .\n", + " # (hates[agatha, i] = 1) => (hates[butler, i] = 1),\n", + " for i in range(n):\n", + " solver.Add((hates[agatha][i] == 1) <= (hates[butler][i] == 1))\n", "\n", - "# Noone hates everyone.\n", - "# forall i : Range .\n", - "# (sum j : Range . hates[i,j]) <= 2,\n", - "for i in range(n):\n", - " solver.Add(solver.Sum([hates[i][j] for j in range(n)]) <= 2)\n", + " # Noone hates everyone.\n", + " # forall i : Range .\n", + " # (sum j : Range . hates[i,j]) <= 2,\n", + " for i in range(n):\n", + " solver.Add(solver.Sum([hates[i][j] for j in range(n)]) <= 2)\n", "\n", - "# Who killed Agatha?\n", - "solver.Add(the_victim == agatha)\n", + " # Who killed Agatha?\n", + " solver.Add(the_victim == agatha)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(the_killer)\n", - "solution.Add(the_victim)\n", - "solution.Add(hates_flat)\n", - "solution.Add(richer_flat)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(the_killer)\n", + " solution.Add(the_victim)\n", + " solution.Add(hates_flat)\n", + " solution.Add(richer_flat)\n", "\n", - "# db: DecisionBuilder\n", - "db = solver.Phase(hates_flat + richer_flat, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE)\n", + " # db: DecisionBuilder\n", + " db = solver.Phase(hates_flat + richer_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(\"the_killer:\", the_killer.Value())\n", + " the_killers[the_killer.Value()] += 1\n", + " print(\"the_victim:\", the_victim.Value())\n", + " print(\"hates:\")\n", + " print_flat_matrix(hates_flat, n, n)\n", + " print(\"richer:\")\n", + " print_flat_matrix(richer_flat, n, n)\n", + " print()\n", + " num_solutions += 1\n", + "\n", + " solver.EndSearch()\n", "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print(\"the_killer:\", the_killer.Value())\n", - " the_killers[the_killer.Value()] += 1\n", - " print(\"the_victim:\", the_victim.Value())\n", - " print(\"hates:\")\n", - " print_flat_matrix(hates_flat, n, n)\n", - " print(\"richer:\")\n", - " print_flat_matrix(richer_flat, n, n)\n", " print()\n", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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", "the_killers = defaultdict(int)\n", - "p = [\"agatha\", \"butler\", \"charles\"]\n" + "p = [\"agatha\", \"butler\", \"charles\"]\n", + "main(the_killers)\n", + "\n", + "print(\"\\n\")\n", + "for k in the_killers:\n", + " print(\"the killer %s was choosen in %i solutions\" % (p[k], the_killers[k]))\n", + "\n" ] } ], diff --git a/examples/notebook/contrib/xkcd.ipynb b/examples/notebook/contrib/xkcd.ipynb index 72b06258b3..6028034178 100644 --- a/examples/notebook/contrib/xkcd.ipynb +++ b/examples/notebook/contrib/xkcd.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " xkcd problem (Knapsack) in Google CP Solver.\n", "\n", @@ -110,74 +95,86 @@ "\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", + " http://www.hakank.org/google_cp_solver/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main():\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"xkcd knapsack\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"xkcd knapsack\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "num_prices = 6\n", - "# for price and total: multiplied by 100 to be able to use integers\n", - "price = [215, 275, 335, 355, 420, 580]\n", - "total = 1505\n", + " #\n", + " # data\n", + " #\n", + " num_prices = 6\n", + " # for price and total: multiplied by 100 to be able to use integers\n", + " price = [215, 275, 335, 355, 420, 580]\n", + " total = 1505\n", "\n", - "products = [\n", - " \"mixed fruit\", \"french fries\", \"side salad\", \"host wings\",\n", - " \"mozzarella sticks\", \"samples place\"\n", - "]\n", + " products = [\n", + " \"mixed fruit\", \"french fries\", \"side salad\", \"host wings\",\n", + " \"mozzarella sticks\", \"samples place\"\n", + " ]\n", "\n", - "# declare variables\n", + " # declare variables\n", "\n", - "# how many items of each dish\n", - "x = [solver.IntVar(0, 10, \"x%i\" % i) for i in range(num_prices)]\n", - "z = solver.IntVar(0, 1505, \"z\")\n", + " # how many items of each dish\n", + " x = [solver.IntVar(0, 10, \"x%i\" % i) for i in range(num_prices)]\n", + " z = solver.IntVar(0, 1505, \"z\")\n", "\n", - "#\n", - "# constraints\n", - "#\n", - "solver.Add(z == solver.Sum([x[i] * price[i] for i in range(num_prices)]))\n", - "solver.Add(z == total)\n", + " #\n", + " # constraints\n", + " #\n", + " solver.Add(z == solver.Sum([x[i] * price[i] for i in range(num_prices)]))\n", + " solver.Add(z == total)\n", "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add([x[i] for i in range(num_prices)])\n", - "solution.Add(z)\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add([x[i] for i in range(num_prices)])\n", + " solution.Add(z)\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([x[i] for i in range(num_prices)], solver.INT_VAR_SIMPLE,\n", - " solver.ASSIGN_MIN_VALUE), [collector])\n", + " collector = solver.AllSolutionCollector(solution)\n", + " # collector = solver.FirstSolutionCollector(solution)\n", + " # search_log = solver.SearchLog(100, x[0])\n", + " solver.Solve(\n", + " solver.Phase([x[i] for i in range(num_prices)], 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", + " print(\"z:\", collector.Value(s, z) / 100.0)\n", + " xval = [collector.Value(s, x[i]) for i in range(num_prices)]\n", + " print(\"x:\", xval)\n", + " for i in range(num_prices):\n", + " if xval[i] > 0:\n", + " print(xval[i], \"of\", products[i], \":\", price[i] / 100.0)\n", + " print()\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", - " print(\"z:\", collector.Value(s, z) / 100.0)\n", - " xval = [collector.Value(s, x[i]) for i in range(num_prices)]\n", - " print(\"x:\", xval)\n", - " for i in range(num_prices):\n", - " if xval[i] > 0:\n", - " print(xval[i], \"of\", products[i], \":\", price[i] / 100.0)\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", - " print()\n", - " print(\"num_solutions:\", num_solutions)\n", - " print(\"failures:\", solver.Failures())\n", - " print(\"branches:\", solver.Branches())\n", - " print(\"WallTime:\", solver.WallTime())\n", + " else:\n", + " print(\"No solutions found\")\n", "\n", - "else:\n", - " print(\"No solutions found\")\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/contrib/young_tableaux.ipynb b/examples/notebook/contrib/young_tableaux.ipynb index ac31319f1a..fc727d4abe 100644 --- a/examples/notebook/contrib/young_tableaux.ipynb +++ b/examples/notebook/contrib/young_tableaux.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "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", " Young tableaux in Google CP Solver.\n", "\n", @@ -134,102 +119,117 @@ "\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", + " http://www.hakank.org/google_or_tools/\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import sys\n", "from ortools.constraint_solver import pywrapcp\n", "\n", "\n", + "def main(n=5):\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver(\"Problem\")\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver(\"Problem\")\n", "\n", - "#\n", - "# data\n", - "#\n", - "print(\"n:\", n)\n", + " #\n", + " # data\n", + " #\n", + " print(\"n:\", 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 + 1, \"x(%i,%i)\" % (i, j))\n", - "\n", - "x_flat = [x[(i, j)] for i in range(n) for j in range(n)]\n", - "\n", - "# partition structure\n", - "p = [solver.IntVar(0, n + 1, \"p%i\" % i) for i in range(n)]\n", - "\n", - "#\n", - "# constraints\n", - "#\n", - "\n", - "# 1..n is used exactly once\n", - "for i in range(1, n + 1):\n", - " solver.Add(solver.Count(x_flat, i, 1))\n", - "\n", - "solver.Add(x[(0, 0)] == 1)\n", - "\n", - "# row wise\n", - "for i in range(n):\n", - " for j in range(1, n):\n", - " solver.Add(x[(i, j)] >= x[(i, j - 1)])\n", - "\n", - "# column wise\n", - "for j in range(n):\n", - " for i in range(1, n):\n", - " solver.Add(x[(i, j)] >= x[(i - 1, j)])\n", - "\n", - "# calculate the structure (the partition)\n", - "for i in range(n):\n", - " # MiniZinc/Zinc version:\n", - " # p[i] == sum(j in 1..n) (bool2int(x[i,j] <= n))\n", - "\n", - " b = [solver.IsLessOrEqualCstVar(x[(i, j)], n) for j in range(n)]\n", - " solver.Add(p[i] == solver.Sum(b))\n", - "\n", - "solver.Add(solver.Sum(p) == n)\n", - "\n", - "for i in range(1, n):\n", - " solver.Add(p[i - 1] >= p[i])\n", - "\n", - "#\n", - "# solution and search\n", - "#\n", - "solution = solver.Assignment()\n", - "solution.Add(x_flat)\n", - "solution.Add(p)\n", - "\n", - "# db: DecisionBuilder\n", - "db = solver.Phase(x_flat + p, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE)\n", - "\n", - "solver.NewSearch(db)\n", - "num_solutions = 0\n", - "while solver.NextSolution():\n", - " print(\"p:\", [p[i].Value() for i in range(n)])\n", - " print(\"x:\")\n", + " #\n", + " # declare variables\n", + " #\n", + " x = {}\n", " for i in range(n):\n", " for j in range(n):\n", - " val = x_flat[i * n + j].Value()\n", - " if val <= n:\n", - " print(val, end=\" \")\n", - " if p[i].Value() > 0:\n", - " print()\n", + " x[(i, j)] = solver.IntVar(1, n + 1, \"x(%i,%i)\" % (i, j))\n", + "\n", + " x_flat = [x[(i, j)] for i in range(n) for j in range(n)]\n", + "\n", + " # partition structure\n", + " p = [solver.IntVar(0, n + 1, \"p%i\" % i) for i in range(n)]\n", + "\n", + " #\n", + " # constraints\n", + " #\n", + "\n", + " # 1..n is used exactly once\n", + " for i in range(1, n + 1):\n", + " solver.Add(solver.Count(x_flat, i, 1))\n", + "\n", + " solver.Add(x[(0, 0)] == 1)\n", + "\n", + " # row wise\n", + " for i in range(n):\n", + " for j in range(1, n):\n", + " solver.Add(x[(i, j)] >= x[(i, j - 1)])\n", + "\n", + " # column wise\n", + " for j in range(n):\n", + " for i in range(1, n):\n", + " solver.Add(x[(i, j)] >= x[(i - 1, j)])\n", + "\n", + " # calculate the structure (the partition)\n", + " for i in range(n):\n", + " # MiniZinc/Zinc version:\n", + " # p[i] == sum(j in 1..n) (bool2int(x[i,j] <= n))\n", + "\n", + " b = [solver.IsLessOrEqualCstVar(x[(i, j)], n) for j in range(n)]\n", + " solver.Add(p[i] == solver.Sum(b))\n", + "\n", + " solver.Add(solver.Sum(p) == n)\n", + "\n", + " for i in range(1, n):\n", + " solver.Add(p[i - 1] >= p[i])\n", + "\n", + " #\n", + " # solution and search\n", + " #\n", + " solution = solver.Assignment()\n", + " solution.Add(x_flat)\n", + " solution.Add(p)\n", + "\n", + " # db: DecisionBuilder\n", + " db = solver.Phase(x_flat + p, solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE)\n", + "\n", + " solver.NewSearch(db)\n", + " num_solutions = 0\n", + " while solver.NextSolution():\n", + " print(\"p:\", [p[i].Value() for i in range(n)])\n", + " print(\"x:\")\n", + " for i in range(n):\n", + " for j in range(n):\n", + " val = x_flat[i * n + j].Value()\n", + " if val <= n:\n", + " print(val, end=\" \")\n", + " if p[i].Value() > 0:\n", + " print()\n", + " print()\n", + " num_solutions += 1\n", + "\n", + " solver.EndSearch()\n", + "\n", " print()\n", - " num_solutions += 1\n", + " print(\"num_solutions:\", num_solutions)\n", + " print(\"failures:\", solver.Failures())\n", + " print(\"branches:\", solver.Branches())\n", + " print(\"WallTime:\", solver.WallTime())\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 = 5\n", + "if len(sys.argv) > 1:\n", + " n = int(sys.argv[1])\n", "\n", - "n = 5\n" + "main(n)\n", + "\n" ] } ], diff --git a/examples/notebook/examples/appointments.ipynb b/examples/notebook/examples/appointments.ipynb index e3228e2ceb..52ff4c2628 100644 --- a/examples/notebook/examples/appointments.ipynb +++ b/examples/notebook/examples/appointments.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,20 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Appointment selection.\n", + "\n", + "This module maximizes the number of appointments that can\n", + "be fulfilled by a crew of installers while staying close to ideal\n", + "ratio of appointment types.\n", + "\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,40 +88,15 @@ "metadata": {}, "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Appointment selection.\n", - "\n", - "This module maximizes the number of appointments that can\n", - "be fulfilled by a crew of installers while staying close to ideal\n", - "ratio of appointment types.\n", - "\"\"\"\n", - "\n", - "# overloaded sum() clashes with pytype.\n", - "# pytype: disable=wrong-arg-types\n", - "\n", - "from absl import app\n", - "from absl import flags\n", "from ortools.linear_solver import pywraplp\n", "from ortools.sat.python import cp_model\n", "\n", - "FLAGS = flags.FLAGS\n", - "flags.DEFINE_integer('load_min', 480, 'Minimum load in minutes.')\n", - "flags.DEFINE_integer('load_max', 540, 'Maximum load in minutes.')\n", - "flags.DEFINE_integer('commute_time', 30, 'Commute time in minutes.')\n", - "flags.DEFINE_integer('num_workers', 98, 'Maximum number of workers.')\n", + "class FLAGS: pass\n", "\n", + "FLAGS.load_min = 480 # Minimum load in minutes.\n", + "FLAGS.load_max = 540 # Maximum load in minutes.\n", + "FLAGS.commute_time = 30 # Commute time in minutes.\n", + "FLAGS.num_workers = 98 # Maximum number of workers.\n", "\n", "class AllSolutionCollector(cp_model.CpSolverSolutionCallback):\n", " \"\"\"Stores all solutions.\"\"\"\n", @@ -280,39 +269,43 @@ " return output\n", "\n", "\n", - "demand = [(45.0, 'Type1', 90), (30.0, 'Type2', 120), (25.0, 'Type3', 180)]\n", - "print('*** input problem ***')\n", - "print('Appointments: ')\n", - "for a in demand:\n", - " print(' %.2f%% of %s : %d min' % (a[0], a[1], a[2]))\n", - "print('Commute time = %d' % FLAGS.commute_time)\n", - "print('Acceptable duration of a work day = [%d..%d]' %\n", - " (FLAGS.load_min, FLAGS.load_max))\n", - "print('%d workers' % FLAGS.num_workers)\n", - "selection = GetOptimalSchedule(demand)\n", - "print()\n", - "installed = 0\n", - "installed_per_type = {}\n", - "for a in demand:\n", - " installed_per_type[a[1]] = 0\n", + "def solve_appointments(_):\n", + " demand = [(45.0, 'Type1', 90), (30.0, 'Type2', 120), (25.0, 'Type3', 180)]\n", + " print('*** input problem ***')\n", + " print('Appointments: ')\n", + " for a in demand:\n", + " print(' %.2f%% of %s : %d min' % (a[0], a[1], a[2]))\n", + " print('Commute time = %d' % FLAGS.commute_time)\n", + " print('Acceptable duration of a work day = [%d..%d]' %\n", + " (FLAGS.load_min, FLAGS.load_max))\n", + " print('%d workers' % FLAGS.num_workers)\n", + " selection = GetOptimalSchedule(demand)\n", + " print()\n", + " installed = 0\n", + " installed_per_type = {}\n", + " for a in demand:\n", + " installed_per_type[a[1]] = 0\n", "\n", - "print('*** output solution ***')\n", - "for template in selection:\n", - " num_instances = template[0]\n", - " print('%d schedules with ' % num_instances)\n", - " for t in template[1]:\n", - " mult = t[0]\n", - " print(' %d installation of type %s' % (mult, t[1]))\n", - " installed += num_instances * mult\n", - " installed_per_type[t[1]] += num_instances * mult\n", + " print('*** output solution ***')\n", + " for template in selection:\n", + " num_instances = template[0]\n", + " print('%d schedules with ' % num_instances)\n", + " for t in template[1]:\n", + " mult = t[0]\n", + " print(' %d installation of type %s' % (mult, t[1]))\n", + " installed += num_instances * mult\n", + " installed_per_type[t[1]] += num_instances * mult\n", "\n", - "print()\n", - "print('%d installations planned' % installed)\n", - "for a in demand:\n", - " name = a[1]\n", - " per_type = installed_per_type[name]\n", - " print((' %d (%.2f%%) installations of type %s planned' %\n", - " (per_type, per_type * 100.0 / installed, name)))\n", + " print()\n", + " print('%d installations planned' % installed)\n", + " for a in demand:\n", + " name = a[1]\n", + " per_type = installed_per_type[name]\n", + " print((' %d (%.2f%%) installations of type %s planned' %\n", + " (per_type, per_type * 100.0 / installed, name)))\n", + "\n", + "\n", + "solve_appointments()\n", "\n" ] } diff --git a/examples/notebook/examples/arc_flow_cutting_stock_sat.ipynb b/examples/notebook/examples/arc_flow_cutting_stock_sat.ipynb index f1a8651cae..e81fb85396 100644 --- a/examples/notebook/examples/arc_flow_cutting_stock_sat.ipynb +++ b/examples/notebook/examples/arc_flow_cutting_stock_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,15 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Cutting stock problem with the objective to minimize wasted space.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,21 +83,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Cutting stock problem with the objective to minimize wasted space.\"\"\"\n", - "\n", - "\n", "import argparse\n", "import collections\n", "import time\n", @@ -338,11 +332,15 @@ " print('No solution')\n", "\n", "\n", - "\"\"\"Main function\"\"\"\n", - "if args.solver == 'sat':\n", - " solve_cutting_stock_with_arc_flow_and_sat(args.output_proto_file)\n", - "else: # 'mip'\n", - " solve_cutting_stock_with_arc_flow_and_mip()\n", + "def main(args):\n", + " \"\"\"Main function\"\"\"\n", + " if args.solver == 'sat':\n", + " solve_cutting_stock_with_arc_flow_and_sat(args.output_proto_file)\n", + " else: # 'mip'\n", + " solve_cutting_stock_with_arc_flow_and_mip()\n", + "\n", + "\n", + "main(PARSER.parse_args())\n", "\n" ] } diff --git a/examples/notebook/examples/assignment2_sat.ipynb b/examples/notebook/examples/assignment2_sat.ipynb index b3f54e1305..4dfc899cdb 100644 --- a/examples/notebook/examples/assignment2_sat.ipynb +++ b/examples/notebook/examples/assignment2_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -90,66 +90,70 @@ "from ortools.sat.python import cp_model\n", "\n", "\n", - "# Instantiate a cp model.\n", - "cost = [[90, 76, 75, 70, 50, 74, 12, 68], [35, 85, 55, 65, 48, 101, 70, 83],\n", - " [125, 95, 90, 105, 59,\n", - " 120, 36, 73], [45, 110, 95, 115, 104, 83, 37,\n", - " 71], [60, 105, 80, 75, 59, 62, 93,\n", - " 88], [45, 65, 110, 95, 47, 31, 81, 34],\n", - " [38, 51, 107, 41, 69, 99, 115,\n", - " 48], [47, 85, 57, 71, 92, 77, 109,\n", - " 36], [39, 63, 97, 49, 118, 56,\n", - " 92, 61], [47, 101, 71, 60, 88, 109, 52, 90]]\n", + "def main():\n", + " # Instantiate a cp model.\n", + " cost = [[90, 76, 75, 70, 50, 74, 12, 68], [35, 85, 55, 65, 48, 101, 70, 83],\n", + " [125, 95, 90, 105, 59,\n", + " 120, 36, 73], [45, 110, 95, 115, 104, 83, 37,\n", + " 71], [60, 105, 80, 75, 59, 62, 93,\n", + " 88], [45, 65, 110, 95, 47, 31, 81, 34],\n", + " [38, 51, 107, 41, 69, 99, 115,\n", + " 48], [47, 85, 57, 71, 92, 77, 109,\n", + " 36], [39, 63, 97, 49, 118, 56,\n", + " 92, 61], [47, 101, 71, 60, 88, 109, 52, 90]]\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", + " 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 = cp_model.CpModel()\n", - "# Variables\n", - "total_cost = model.NewIntVar(0, 1000, 'total_cost')\n", - "x = []\n", - "for i in all_workers:\n", - " t = []\n", - " for j in all_tasks:\n", - " t.append(model.NewBoolVar('x[%i,%i]' % (i, j)))\n", - " x.append(t)\n", - "\n", - "# Constraints\n", - "\n", - "# Each task is assigned to at least one worker.\n", - "[model.Add(sum(x[i][j] for i in all_workers) >= 1) for j in all_tasks]\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", - "# Total cost\n", - "model.Add(total_cost == sum(x[i][j] * cost[i][j]\n", - " for j in all_tasks for i in all_workers))\n", - "model.Minimize(total_cost)\n", - "\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", + " model = cp_model.CpModel()\n", + " # Variables\n", + " total_cost = model.NewIntVar(0, 1000, 'total_cost')\n", + " x = []\n", " for i in all_workers:\n", + " t = []\n", " for j in all_tasks:\n", - " if solver.Value(x[i][j]) == 1:\n", - " print('Worker ', i, ' assigned to task ', j, ' Cost = ',\n", - " cost[i][j])\n", + " t.append(model.NewBoolVar('x[%i,%i]' % (i, j)))\n", + " x.append(t)\n", "\n", - " print()\n", + " # Constraints\n", "\n", - "print('Statistics')\n", - "print(' - conflicts : %i' % solver.NumConflicts())\n", - "print(' - branches : %i' % solver.NumBranches())\n", - "print(' - wall time : %f s' % solver.WallTime())\n", + " # Each task is assigned to at least one worker.\n", + " [model.Add(sum(x[i][j] for i in all_workers) >= 1) for j in all_tasks]\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", + " # Total cost\n", + " model.Add(total_cost == sum(x[i][j] * cost[i][j]\n", + " for j in all_tasks for i in all_workers))\n", + " model.Minimize(total_cost)\n", + "\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 = ',\n", + " 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 s' % solver.WallTime())\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/assignment_with_constraints_sat.ipynb b/examples/notebook/examples/assignment_with_constraints_sat.ipynb index b7f4558b87..21ec3d5abb 100644 --- a/examples/notebook/examples/assignment_with_constraints_sat.ipynb +++ b/examples/notebook/examples/assignment_with_constraints_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,15 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Solve an assignment problem with combination constraints on workers.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,21 +83,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Solve an assignment problem with combination constraints on workers.\"\"\"\n", - "\n", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", diff --git a/examples/notebook/examples/balance_group_sat.ipynb b/examples/notebook/examples/balance_group_sat.ipynb index 47bff70bab..d675f90558 100644 --- a/examples/notebook/examples/balance_group_sat.ipynb +++ b/examples/notebook/examples/balance_group_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,21 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "We are trying to group items in equal sized groups.\n", + "\n", + "Each item has a color and a value. We want the sum of values of each group to\n", + "be as close to the average as possible.\n", + "Furthermore, if one color is an a group, at least k items with this color must\n", + "be in that group.\n", + "\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,27 +89,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"We are trying to group items in equal sized groups.\n", - "\n", - "Each item has a color and a value. We want the sum of values of each group to\n", - "be as close to the average as possible.\n", - "Furthermore, if one color is an a group, at least k items with this color must\n", - "be in that group.\n", - "\"\"\"\n", - "\n", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", @@ -136,118 +130,122 @@ " print(']')\n", "\n", "\n", - "# Data.\n", - "num_groups = 10\n", - "num_items = 100\n", - "num_colors = 3\n", - "min_items_of_same_color_per_group = 4\n", + "def main():\n", + " # Data.\n", + " num_groups = 10\n", + " num_items = 100\n", + " num_colors = 3\n", + " min_items_of_same_color_per_group = 4\n", "\n", - "all_groups = range(num_groups)\n", - "all_items = range(num_items)\n", - "all_colors = range(num_colors)\n", + " all_groups = range(num_groups)\n", + " all_items = range(num_items)\n", + " all_colors = range(num_colors)\n", "\n", - "# Values for each items.\n", - "values = [1 + i + (i * i // 200) for i in all_items]\n", - "# Color for each item (simple modulo).\n", - "colors = [i % num_colors for i in all_items]\n", + " # Values for each items.\n", + " values = [1 + i + (i * i // 200) for i in all_items]\n", + " # Color for each item (simple modulo).\n", + " colors = [i % num_colors for i in all_items]\n", "\n", - "sum_of_values = sum(values)\n", - "average_sum_per_group = sum_of_values // num_groups\n", + " sum_of_values = sum(values)\n", + " average_sum_per_group = sum_of_values // num_groups\n", "\n", - "num_items_per_group = num_items // num_groups\n", + " num_items_per_group = num_items // num_groups\n", "\n", - "# Collect all items in a given color.\n", - "items_per_color = {}\n", - "for c in all_colors:\n", - " items_per_color[c] = []\n", - " for i in all_items:\n", - " if colors[i] == c:\n", - " items_per_color[c].append(i)\n", - "\n", - "print('Model has %i items, %i groups, and %i colors' %\n", - " (num_items, num_groups, num_colors))\n", - "print(' average sum per group = %i' % average_sum_per_group)\n", - "\n", - "# Model.\n", - "\n", - "model = cp_model.CpModel()\n", - "\n", - "item_in_group = {}\n", - "for i in all_items:\n", - " for g in all_groups:\n", - " item_in_group[(i, g)] = model.NewBoolVar('item %d in group %d' %\n", - " (i, g))\n", - "\n", - "# Each group must have the same size.\n", - "for g in all_groups:\n", - " model.Add(\n", - " sum(item_in_group[(i, g)]\n", - " for i in all_items) == num_items_per_group)\n", - "\n", - "# One item must belong to exactly one group.\n", - "for i in all_items:\n", - " model.Add(sum(item_in_group[(i, g)] for g in all_groups) == 1)\n", - "\n", - "# The deviation of the sum of each items in a group against the average.\n", - "e = model.NewIntVar(0, 550, 'epsilon')\n", - "\n", - "# Constrain the sum of values in one group around the average sum per group.\n", - "for g in all_groups:\n", - " model.Add(\n", - " sum(item_in_group[(i, g)] * values[i]\n", - " for i in all_items) <= average_sum_per_group + e)\n", - " model.Add(\n", - " sum(item_in_group[(i, g)] * values[i]\n", - " for i in all_items) >= average_sum_per_group - e)\n", - "\n", - "# color_in_group variables.\n", - "color_in_group = {}\n", - "for g in all_groups:\n", + " # Collect all items in a given color.\n", + " items_per_color = {}\n", " for c in all_colors:\n", - " color_in_group[(c, g)] = model.NewBoolVar(\n", - " 'color %d is in group %d' % (c, g))\n", + " items_per_color[c] = []\n", + " for i in all_items:\n", + " if colors[i] == c:\n", + " items_per_color[c].append(i)\n", "\n", - "# Item is in a group implies its color is in that group.\n", - "for i in all_items:\n", - " for g in all_groups:\n", - " model.AddImplication(item_in_group[(i, g)],\n", - " color_in_group[(colors[i], g)])\n", + " print('Model has %i items, %i groups, and %i colors' %\n", + " (num_items, num_groups, num_colors))\n", + " print(' average sum per group = %i' % average_sum_per_group)\n", "\n", - "# If a color is in a group, it must contains at least\n", - "# min_items_of_same_color_per_group items from that color.\n", - "for c in all_colors:\n", - " for g in all_groups:\n", - " literal = color_in_group[(c, g)]\n", - " model.Add(\n", - " sum(item_in_group[(i, g)] for i in items_per_color[c]) >=\n", - " min_items_of_same_color_per_group).OnlyEnforceIf(literal)\n", + " # Model.\n", "\n", - "# Compute the maximum number of colors in a group.\n", - "max_color = num_items_per_group // min_items_of_same_color_per_group\n", - "# Redundant contraint: The problem does not solve in reasonable time without it.\n", - "if max_color < num_colors:\n", + " model = cp_model.CpModel()\n", + "\n", + " item_in_group = {}\n", + " for i in all_items:\n", + " for g in all_groups:\n", + " item_in_group[(i, g)] = model.NewBoolVar('item %d in group %d' %\n", + " (i, g))\n", + "\n", + " # Each group must have the same size.\n", " for g in all_groups:\n", " model.Add(\n", - " sum(color_in_group[(c, g)] for c in all_colors) <= max_color)\n", + " sum(item_in_group[(i, g)]\n", + " for i in all_items) == num_items_per_group)\n", "\n", - "# Minimize epsilon\n", - "model.Minimize(e)\n", + " # One item must belong to exactly one group.\n", + " for i in all_items:\n", + " model.Add(sum(item_in_group[(i, g)] for g in all_groups) == 1)\n", "\n", - "model.ExportToFile('balance_group_sat.pbtxt')\n", + " # The deviation of the sum of each items in a group against the average.\n", + " e = model.NewIntVar(0, 550, 'epsilon')\n", "\n", - "solver = cp_model.CpSolver()\n", - "solution_printer = SolutionPrinter(values, colors, all_groups, all_items,\n", - " item_in_group)\n", - "status = solver.Solve(model, solution_printer)\n", + " # Constrain the sum of values in one group around the average sum per group.\n", + " for g in all_groups:\n", + " model.Add(\n", + " sum(item_in_group[(i, g)] * values[i]\n", + " for i in all_items) <= average_sum_per_group + e)\n", + " model.Add(\n", + " sum(item_in_group[(i, g)] * values[i]\n", + " for i in all_items) >= average_sum_per_group - e)\n", "\n", - "if status == cp_model.OPTIMAL:\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", - "else:\n", - " print('No solution found')\n", + " # color_in_group variables.\n", + " color_in_group = {}\n", + " for g in all_groups:\n", + " for c in all_colors:\n", + " color_in_group[(c, g)] = model.NewBoolVar(\n", + " 'color %d is in group %d' % (c, g))\n", + "\n", + " # Item is in a group implies its color is in that group.\n", + " for i in all_items:\n", + " for g in all_groups:\n", + " model.AddImplication(item_in_group[(i, g)],\n", + " color_in_group[(colors[i], g)])\n", + "\n", + " # If a color is in a group, it must contains at least\n", + " # min_items_of_same_color_per_group items from that color.\n", + " for c in all_colors:\n", + " for g in all_groups:\n", + " literal = color_in_group[(c, g)]\n", + " model.Add(\n", + " sum(item_in_group[(i, g)] for i in items_per_color[c]) >=\n", + " min_items_of_same_color_per_group).OnlyEnforceIf(literal)\n", + "\n", + " # Compute the maximum number of colors in a group.\n", + " max_color = num_items_per_group // min_items_of_same_color_per_group\n", + " # Redundant contraint: The problem does not solve in reasonable time without it.\n", + " if max_color < num_colors:\n", + " for g in all_groups:\n", + " model.Add(\n", + " sum(color_in_group[(c, g)] for c in all_colors) <= max_color)\n", + "\n", + " # Minimize epsilon\n", + " model.Minimize(e)\n", + "\n", + " model.ExportToFile('balance_group_sat.pbtxt')\n", + "\n", + " solver = cp_model.CpSolver()\n", + " solution_printer = SolutionPrinter(values, colors, all_groups, all_items,\n", + " item_in_group)\n", + " status = solver.Solve(model, solution_printer)\n", + "\n", + " if status == cp_model.OPTIMAL:\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", + " else:\n", + " print('No solution found')\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/bus_driver_scheduling_flow_sat.ipynb b/examples/notebook/examples/bus_driver_scheduling_flow_sat.ipynb index fd155d9235..b7b3f2e39c 100644 --- a/examples/notebook/examples/bus_driver_scheduling_flow_sat.ipynb +++ b/examples/notebook/examples/bus_driver_scheduling_flow_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,25 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"This model implements a bus driver scheduling problem.\n", + "This model implements a bus driver scheduling problem.\n", "\n", "Constraints:\n", "- max driving time per driver <= 9h\n", @@ -96,8 +82,16 @@ "- 10 min preparation time before the first shift\n", "- 15 min cleaning time after the last shift\n", "- 2 min waiting time after each shift for passenger boarding and alighting\n", - "\"\"\"\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import argparse\n", "import collections\n", "import math\n", @@ -1881,19 +1875,23 @@ " return optimal_num_drivers\n", "\n", "\n", - "\"\"\"Optimize the bus driver allocation in two passes.\"\"\"\n", - "print('----------- first pass: minimize the number of drivers')\n", - "shifts = []\n", - "if args.instance == 1:\n", - " shifts = SAMPLE_SHIFTS_SMALL\n", - "elif args.instance == 2:\n", - " shifts = SAMPLE_SHIFTS_MEDIUM\n", - "elif args.instance == 3:\n", - " shifts = SAMPLE_SHIFTS_LARGE\n", - "num_drivers = find_minimum_number_of_drivers(shifts, args.params)\n", + "def main(args):\n", + " \"\"\"Optimize the bus driver allocation in two passes.\"\"\"\n", + " print('----------- first pass: minimize the number of drivers')\n", + " shifts = []\n", + " if args.instance == 1:\n", + " shifts = SAMPLE_SHIFTS_SMALL\n", + " elif args.instance == 2:\n", + " shifts = SAMPLE_SHIFTS_MEDIUM\n", + " elif args.instance == 3:\n", + " shifts = SAMPLE_SHIFTS_LARGE\n", + " num_drivers = find_minimum_number_of_drivers(shifts, args.params)\n", "\n", - "print('----------- second pass: minimize the sum of working times')\n", - "#bus_driver_scheduling(False, num_drivers)\n", + " print('----------- second pass: minimize the sum of working times')\n", + " #bus_driver_scheduling(False, num_drivers)\n", + "\n", + "\n", + "main(PARSER.parse_args())\n", "\n" ] } diff --git a/examples/notebook/examples/bus_driver_scheduling_sat.ipynb b/examples/notebook/examples/bus_driver_scheduling_sat.ipynb index 6aec20c939..40c874e338 100644 --- a/examples/notebook/examples/bus_driver_scheduling_sat.ipynb +++ b/examples/notebook/examples/bus_driver_scheduling_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"This model implements a bus driver scheduling problem.\n", + "This model implements a bus driver scheduling problem.\n", "\n", "Constraints:\n", "- max driving time per driver <= 9h\n", @@ -97,24 +82,27 @@ "- 10 min preparation time before the first shift\n", "- 15 min cleaning time after the last shift\n", "- 2 min waiting time after each shift for passenger boarding and alighting\n", - "\"\"\"\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import collections\n", "import math\n", "\n", - "from absl import app\n", - "from absl import flags\n", "from google.protobuf import text_format\n", "from ortools.sat.python import cp_model\n", "\n", - "FLAGS = flags.FLAGS\n", - "\n", - "flags.DEFINE_string('output_proto', '',\n", - " 'Output file to write the cp_model proto to.')\n", - "flags.DEFINE_string('params', 'num_search_workers:8,log_search_progress:true',\n", - " 'Sat solver parameters.')\n", - "flags.DEFINE_integer('instance', 1, 'Instance to select (1, 2, 3).', 1, 3)\n", + "class FLAGS: pass\n", "\n", + "FLAGS.output_proto = '' # Output file to write the cp_model proto to.\n", + "FLAGS.params = 'num_search_workers:8,log_search_progress:true' # Sat solver parameters.\n", + "FLAGS.instance = 1 # Instance to select (1, 2, 3).\n", "SAMPLE_SHIFTS_SMALL = [\n", " #\n", " # column description:\n", @@ -2054,14 +2042,22 @@ " return int(solver.ObjectiveValue())\n", "\n", "\n", - "\"\"\"Optimize the bus driver allocation in two passes.\"\"\"\n", - "print('----------- first pass: minimize the number of drivers')\n", - "num_drivers = bus_driver_scheduling(True, -1)\n", - "if num_drivers == -1:\n", - " print('no solution found, skipping the final step')\n", - "else:\n", - " print('----------- second pass: minimize the sum of working times')\n", - " bus_driver_scheduling(False, num_drivers)\n", + "def solve_bus_driver_scheduling():\n", + " \"\"\"Optimize the bus driver allocation in two passes.\"\"\"\n", + " print('----------- first pass: minimize the number of drivers')\n", + " num_drivers = bus_driver_scheduling(True, -1)\n", + " if num_drivers == -1:\n", + " print('no solution found, skipping the final step')\n", + " else:\n", + " print('----------- second pass: minimize the sum of working times')\n", + " bus_driver_scheduling(False, num_drivers)\n", + "\n", + "\n", + "def main(_):\n", + " solve_bus_driver_scheduling()\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/chemical_balance_lp.ipynb b/examples/notebook/examples/chemical_balance_lp.ipynb index a70afbd4a1..0247281b82 100644 --- a/examples/notebook/examples/chemical_balance_lp.ipynb +++ b/examples/notebook/examples/chemical_balance_lp.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { diff --git a/examples/notebook/examples/chemical_balance_sat.ipynb b/examples/notebook/examples/chemical_balance_sat.ipynb index bd7e6aad1d..7fa3c186d3 100644 --- a/examples/notebook/examples/chemical_balance_sat.ipynb +++ b/examples/notebook/examples/chemical_balance_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { diff --git a/examples/notebook/examples/clustering_sat.ipynb b/examples/notebook/examples/clustering_sat.ipynb index cbd2742b3c..9c78f10a11 100644 --- a/examples/notebook/examples/clustering_sat.ipynb +++ b/examples/notebook/examples/clustering_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,15 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Cluster 40 cities in 4 equal groups to minimize sum of crossed distances.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,21 +83,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Cluster 40 cities in 4 equal groups to minimize sum of crossed distances.\"\"\"\n", - "\n", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", @@ -136,68 +130,72 @@ " ] # yapf: disable\n", "\n", "\n", - "\"\"\"Entry point of the program.\"\"\"\n", - "num_nodes = len(distance_matrix)\n", - "print('Num nodes =', num_nodes)\n", + "def main():\n", + " \"\"\"Entry point of the program.\"\"\"\n", + " num_nodes = len(distance_matrix)\n", + " print('Num nodes =', num_nodes)\n", "\n", - "# Number of groups to split the nodes, must divide num_nodes.\n", - "num_groups = 4\n", - "group_size = num_nodes // num_groups\n", + " # Number of groups to split the nodes, must divide num_nodes.\n", + " num_groups = 4\n", + " group_size = num_nodes // num_groups\n", "\n", - "# Model.\n", - "model = cp_model.CpModel()\n", + " # Model.\n", + " model = cp_model.CpModel()\n", "\n", - "# Variables.\n", - "neighbors = {}\n", - "obj_vars = []\n", - "obj_coeffs = []\n", - "for n1 in range(num_nodes - 1):\n", - " for n2 in range(n1 + 1, num_nodes):\n", - " same = model.NewBoolVar('neighbors_%i_%i' % (n1, n2))\n", - " neighbors[n1, n2] = same\n", - " obj_vars.append(same)\n", - " obj_coeffs.append(distance_matrix[n1][n2] + distance_matrix[n2][n1])\n", + " # Variables.\n", + " neighbors = {}\n", + " obj_vars = []\n", + " obj_coeffs = []\n", + " for n1 in range(num_nodes - 1):\n", + " for n2 in range(n1 + 1, num_nodes):\n", + " same = model.NewBoolVar('neighbors_%i_%i' % (n1, n2))\n", + " neighbors[n1, n2] = same\n", + " obj_vars.append(same)\n", + " obj_coeffs.append(distance_matrix[n1][n2] + distance_matrix[n2][n1])\n", "\n", - "# Number of neighborss:\n", - "for n in range(num_nodes):\n", - " model.Add(sum(neighbors[m, n] for m in range(n)) + \n", - " sum(neighbors[n, m] for m in range(n + 1, num_nodes)) ==\n", - " group_size - 1)\n", - "\n", - "# Enforce transivity on all triplets.\n", - "for n1 in range(num_nodes - 2):\n", - " for n2 in range(n1 + 1, num_nodes - 1):\n", - " for n3 in range(n2 + 1, num_nodes):\n", - " model.Add(\n", - " neighbors[n1, n3] + neighbors[n2, n3] + neighbors[n1, n2] != 2)\n", - "\n", - "# Redundant constraints on total sum of neighborss.\n", - "model.Add(sum(obj_vars) == num_groups * group_size * (group_size - 1) // 2)\n", - "\n", - "# Minimize weighted sum of arcs.\n", - "model.Minimize(\n", - " sum(obj_vars[i] * obj_coeffs[i] for i in range(len(obj_vars))))\n", - "\n", - "# Solve and print out the solution.\n", - "solver = cp_model.CpSolver()\n", - "solver.parameters.log_search_progress = True\n", - "solver.parameters.num_search_workers = 8\n", - "\n", - "status = solver.Solve(model)\n", - "print(solver.ResponseStats())\n", - "\n", - "visited = set()\n", - "for g in range(num_groups):\n", + " # Number of neighborss:\n", " for n in range(num_nodes):\n", - " if not n in visited:\n", - " visited.add(n)\n", - " output = str(n)\n", - " for o in range(n + 1, num_nodes):\n", - " if solver.BooleanValue(neighbors[n, o]):\n", - " visited.add(o)\n", - " output += ' ' + str(o)\n", - " print('Group', g, ':', output)\n", - " break\n", + " model.Add(sum(neighbors[m, n] for m in range(n)) + \n", + " sum(neighbors[n, m] for m in range(n + 1, num_nodes)) ==\n", + " group_size - 1)\n", + " \n", + " # Enforce transivity on all triplets.\n", + " for n1 in range(num_nodes - 2):\n", + " for n2 in range(n1 + 1, num_nodes - 1):\n", + " for n3 in range(n2 + 1, num_nodes):\n", + " model.Add(\n", + " neighbors[n1, n3] + neighbors[n2, n3] + neighbors[n1, n2] != 2)\n", + "\n", + " # Redundant constraints on total sum of neighborss.\n", + " model.Add(sum(obj_vars) == num_groups * group_size * (group_size - 1) // 2)\n", + "\n", + " # Minimize weighted sum of arcs.\n", + " model.Minimize(\n", + " sum(obj_vars[i] * obj_coeffs[i] for i in range(len(obj_vars))))\n", + "\n", + " # Solve and print out the solution.\n", + " solver = cp_model.CpSolver()\n", + " solver.parameters.log_search_progress = True\n", + " solver.parameters.num_search_workers = 8\n", + "\n", + " status = solver.Solve(model)\n", + " print(solver.ResponseStats())\n", + "\n", + " visited = set()\n", + " for g in range(num_groups):\n", + " for n in range(num_nodes):\n", + " if not n in visited:\n", + " visited.add(n)\n", + " output = str(n)\n", + " for o in range(n + 1, num_nodes):\n", + " if solver.BooleanValue(neighbors[n, o]):\n", + " visited.add(o)\n", + " output += ' ' + str(o)\n", + " print('Group', g, ':', output)\n", + " break\n", + "\n", + "\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/cover_rectangle_sat.ipynb b/examples/notebook/examples/cover_rectangle_sat.ipynb index 65e23099a7..24a5dd3be1 100644 --- a/examples/notebook/examples/cover_rectangle_sat.ipynb +++ b/examples/notebook/examples/cover_rectangle_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -67,6 +67,15 @@ "!pip install ortools" ] }, + { + "cell_type": "markdown", + "id": "description", + "metadata": {}, + "source": [ + "Fill a 72x37 rectangle by a minimum number of non-overlapping squares.\n", + "\n" + ] + }, { "cell_type": "code", "execution_count": null, @@ -74,21 +83,6 @@ "metadata": {}, "outputs": [], "source": [ - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Fill a 72x37 rectangle by a minimum number of non-overlapping squares.\"\"\"\n", - "\n", - "\n", "from ortools.sat.python import cp_model\n", "\n", "\n", diff --git a/examples/notebook/examples/cvrptw_plot.ipynb b/examples/notebook/examples/cvrptw_plot.ipynb index 6fd73f85f0..3b193ea378 100644 --- a/examples/notebook/examples/cvrptw_plot.ipynb +++ b/examples/notebook/examples/cvrptw_plot.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "# This Python file uses the following encoding: utf-8\n", - "# Copyright 2015 Tin Arm Engineering AB\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 (and optional orders).\n", + "Capacitated Vehicle Routing Problem with Time Windows (and optional orders).\n", "\n", " This is a sample using the routing library python wrapper to solve a\n", " CVRPTW problem.\n", @@ -108,8 +93,16 @@ " The optimization engine uses local search to improve solutions, first\n", " solutions being generated using a cheapest addition heuristic.\n", " Numpy and Matplotlib are required for the problem creation and display.\n", - "\n", - "\"\"\"\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import os\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", @@ -650,178 +643,182 @@ " color=cmap(veh_number + 1))\n", "\n", "\n", - "# Create a set of customer, (and depot) stops.\n", - "customers = Customers(\n", - " num_stops=50,\n", - " min_demand=1,\n", - " max_demand=15,\n", - " box_size=40,\n", - " min_tw=3,\n", - " max_tw=6)\n", + "def main():\n", + " # Create a set of customer, (and depot) stops.\n", + " customers = Customers(\n", + " num_stops=50,\n", + " min_demand=1,\n", + " max_demand=15,\n", + " box_size=40,\n", + " min_tw=3,\n", + " max_tw=6)\n", "\n", - "# Create a list of inhomgenious vehicle capacities as integer units.\n", - "capacity = [50, 75, 100, 125, 150, 175, 200, 250]\n", + " # Create a list of inhomgenious vehicle capacities as integer units.\n", + " capacity = [50, 75, 100, 125, 150, 175, 200, 250]\n", "\n", - "# Create a list of inhomogeneous fixed vehicle costs.\n", - "cost = [int(100 + 2 * np.sqrt(c)) for c in capacity]\n", + " # Create a list of inhomogeneous fixed vehicle costs.\n", + " cost = [int(100 + 2 * np.sqrt(c)) for c in capacity]\n", "\n", - "# Create a set of vehicles, the number set by the length of capacity.\n", - "vehicles = Vehicles(capacity=capacity, cost=cost)\n", + " # Create a set of vehicles, the number set by the length of capacity.\n", + " vehicles = Vehicles(capacity=capacity, cost=cost)\n", "\n", - "# check to see that the problem is feasible, if we don't have enough\n", - "# vehicles to cover the demand, there is no point in going further.\n", - "assert (customers.get_total_demand() < vehicles.get_total_capacity())\n", + " # check to see that the problem is feasible, if we don't have enough\n", + " # vehicles to cover the demand, there is no point in going further.\n", + " assert (customers.get_total_demand() < vehicles.get_total_capacity())\n", "\n", - "# Set the starting nodes, and create a callback fn for the starting node.\n", - "start_fn = vehicles.return_starting_callback(\n", - " customers, sameStartFinish=False)\n", + " # Set the starting nodes, and create a callback fn for the starting node.\n", + " start_fn = vehicles.return_starting_callback(\n", + " customers, sameStartFinish=False)\n", "\n", - "# Create the routing index manager.\n", - "manager = pywrapcp.RoutingIndexManager(\n", - " customers.number, # int number\n", - " vehicles.number, # int number\n", - " vehicles.starts, # List of int start depot\n", - " vehicles.ends) # List of int end depot\n", + " # Create the routing index manager.\n", + " manager = pywrapcp.RoutingIndexManager(\n", + " customers.number, # int number\n", + " vehicles.number, # int number\n", + " vehicles.starts, # List of int start depot\n", + " vehicles.ends) # List of int end depot\n", "\n", - "customers.set_manager(manager)\n", + " customers.set_manager(manager)\n", "\n", - "# Set model parameters\n", - "model_parameters = pywrapcp.DefaultRoutingModelParameters()\n", + " # Set model parameters\n", + " model_parameters = pywrapcp.DefaultRoutingModelParameters()\n", "\n", - "# The solver parameters can be accessed from the model parameters. For example :\n", - "# model_parameters.solver_parameters.CopyFrom(\n", - "# pywrapcp.Solver.DefaultSolverParameters())\n", - "# model_parameters.solver_parameters.trace_propagation = True\n", + " # The solver parameters can be accessed from the model parameters. For example :\n", + " # model_parameters.solver_parameters.CopyFrom(\n", + " # pywrapcp.Solver.DefaultSolverParameters())\n", + " # model_parameters.solver_parameters.trace_propagation = True\n", "\n", - "# Make the routing model instance.\n", - "routing = pywrapcp.RoutingModel(manager, model_parameters)\n", + " # Make the routing model instance.\n", + " routing = pywrapcp.RoutingModel(manager, model_parameters)\n", "\n", - "parameters = pywrapcp.DefaultRoutingSearchParameters()\n", - "# Setting first solution heuristic (cheapest addition).\n", - "parameters.first_solution_strategy = (\n", - " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", - "# Routing: forbids use of TSPOpt neighborhood, (this is the default behaviour)\n", - "parameters.local_search_operators.use_tsp_opt = pywrapcp.BOOL_FALSE\n", - "# Disabling Large Neighborhood Search, (this is the default behaviour)\n", - "parameters.local_search_operators.use_path_lns = pywrapcp.BOOL_FALSE\n", - "parameters.local_search_operators.use_inactive_lns = pywrapcp.BOOL_FALSE\n", + " parameters = pywrapcp.DefaultRoutingSearchParameters()\n", + " # Setting first solution heuristic (cheapest addition).\n", + " parameters.first_solution_strategy = (\n", + " routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)\n", + " # Routing: forbids use of TSPOpt neighborhood, (this is the default behaviour)\n", + " parameters.local_search_operators.use_tsp_opt = pywrapcp.BOOL_FALSE\n", + " # Disabling Large Neighborhood Search, (this is the default behaviour)\n", + " parameters.local_search_operators.use_path_lns = pywrapcp.BOOL_FALSE\n", + " parameters.local_search_operators.use_inactive_lns = pywrapcp.BOOL_FALSE\n", "\n", - "parameters.time_limit.seconds = 10\n", - "parameters.use_full_propagation = True\n", - "#parameters.log_search = True\n", + " parameters.time_limit.seconds = 10\n", + " parameters.use_full_propagation = True\n", + " #parameters.log_search = True\n", "\n", - "# Create callback fns for distances, demands, service and transit-times.\n", - "dist_fn = customers.return_dist_callback()\n", - "dist_fn_index = routing.RegisterTransitCallback(dist_fn)\n", + " # Create callback fns for distances, demands, service and transit-times.\n", + " dist_fn = customers.return_dist_callback()\n", + " dist_fn_index = routing.RegisterTransitCallback(dist_fn)\n", "\n", - "dem_fn = customers.return_dem_callback()\n", - "dem_fn_index = routing.RegisterUnaryTransitCallback(dem_fn)\n", + " dem_fn = customers.return_dem_callback()\n", + " dem_fn_index = routing.RegisterUnaryTransitCallback(dem_fn)\n", "\n", - "# Create and register a transit callback.\n", - "serv_time_fn = customers.make_service_time_call_callback()\n", - "transit_time_fn = customers.make_transit_time_callback()\n", - "def tot_time_fn(from_index, to_index):\n", + " # Create and register a transit callback.\n", + " serv_time_fn = customers.make_service_time_call_callback()\n", + " transit_time_fn = customers.make_transit_time_callback()\n", + " def tot_time_fn(from_index, to_index):\n", + " \"\"\"\n", + " The time function we want is both transit time and service time.\n", + " \"\"\"\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 serv_time_fn(from_node, to_node) + transit_time_fn(from_node, to_node)\n", + "\n", + " tot_time_fn_index = routing.RegisterTransitCallback(tot_time_fn)\n", + "\n", + " # Set the cost function (distance callback) for each arc, homogeneous for\n", + " # all vehicles.\n", + " routing.SetArcCostEvaluatorOfAllVehicles(dist_fn_index)\n", + "\n", + " # Set vehicle costs for each vehicle, not homogeneous.\n", + " for veh in vehicles.vehicles:\n", + " routing.SetFixedCostOfVehicle(veh.cost, int(veh.index))\n", + "\n", + " # Add a dimension for vehicle capacities\n", + " null_capacity_slack = 0\n", + " routing.AddDimensionWithVehicleCapacity(\n", + " dem_fn_index, # demand callback\n", + " null_capacity_slack,\n", + " capacity, # capacity array\n", + " True,\n", + " 'Capacity')\n", + " # Add a dimension for time and a limit on the total time_horizon\n", + " routing.AddDimension(\n", + " tot_time_fn_index, # total time function callback\n", + " customers.time_horizon,\n", + " customers.time_horizon,\n", + " True,\n", + " 'Time')\n", + "\n", + " time_dimension = routing.GetDimensionOrDie('Time')\n", + " for cust in customers.customers:\n", + " if cust.tw_open is not None:\n", + " time_dimension.CumulVar(manager.NodeToIndex(cust.index)).SetRange(\n", + " cust.tw_open.seconds, cust.tw_close.seconds)\n", " \"\"\"\n", - " The time function we want is both transit time and service time.\n", + " To allow the dropping of orders, we add disjunctions to all the customer\n", + " nodes. Each disjunction is a list of 1 index, which allows that customer to\n", + " be active or not, with a penalty if not. The penalty should be larger\n", + " than the cost of servicing that customer, or it will always be dropped!\n", " \"\"\"\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 serv_time_fn(from_node, to_node) + transit_time_fn(from_node, to_node)\n", + " # To add disjunctions just to the customers, make a list of non-depots.\n", + " non_depot = set(range(customers.number))\n", + " non_depot.difference_update(vehicles.starts)\n", + " non_depot.difference_update(vehicles.ends)\n", + " penalty = 400000 # The cost for dropping a node from the plan.\n", + " nodes = [routing.AddDisjunction([manager.NodeToIndex(c)], penalty) for c in non_depot]\n", "\n", - "tot_time_fn_index = routing.RegisterTransitCallback(tot_time_fn)\n", + " # This is how you would implement partial routes if you already knew part\n", + " # of a feasible solution for example:\n", + " # partial = np.random.choice(list(non_depot), size=(4,5), replace=False)\n", "\n", - "# Set the cost function (distance callback) for each arc, homogeneous for\n", - "# all vehicles.\n", - "routing.SetArcCostEvaluatorOfAllVehicles(dist_fn_index)\n", + " # routing.CloseModel()\n", + " # partial_list = [partial[0,:].tolist(),\n", + " # partial[1,:].tolist(),\n", + " # partial[2,:].tolist(),\n", + " # partial[3,:].tolist(),\n", + " # [],[],[],[]]\n", + " # print(routing.ApplyLocksToAllVehicles(partial_list, False))\n", "\n", - "# Set vehicle costs for each vehicle, not homogeneous.\n", - "for veh in vehicles.vehicles:\n", - " routing.SetFixedCostOfVehicle(veh.cost, int(veh.index))\n", + " # Solve the problem !\n", + " assignment = routing.SolveWithParameters(parameters)\n", "\n", - "# Add a dimension for vehicle capacities\n", - "null_capacity_slack = 0\n", - "routing.AddDimensionWithVehicleCapacity(\n", - " dem_fn_index, # demand callback\n", - " null_capacity_slack,\n", - " capacity, # capacity array\n", - " True,\n", - " 'Capacity')\n", - "# Add a dimension for time and a limit on the total time_horizon\n", - "routing.AddDimension(\n", - " tot_time_fn_index, # total time function callback\n", - " customers.time_horizon,\n", - " customers.time_horizon,\n", - " True,\n", - " 'Time')\n", + " # The rest is all optional for saving, printing or plotting the solution.\n", + " if assignment:\n", + " ## save the assignment, (Google Protobuf format)\n", + " #save_file_base = os.path.realpath(__file__).split('.')[0]\n", + " #if routing.WriteAssignment(save_file_base + '_assignment.ass'):\n", + " # print('succesfully wrote assignment to file ' + save_file_base +\n", + " # '_assignment.ass')\n", "\n", - "time_dimension = routing.GetDimensionOrDie('Time')\n", - "for cust in customers.customers:\n", - " if cust.tw_open is not None:\n", - " time_dimension.CumulVar(manager.NodeToIndex(cust.index)).SetRange(\n", - " cust.tw_open.seconds, cust.tw_close.seconds)\n", - "\"\"\"\n", - " To allow the dropping of orders, we add disjunctions to all the customer\n", - "nodes. Each disjunction is a list of 1 index, which allows that customer to\n", - "be active or not, with a penalty if not. The penalty should be larger\n", - "than the cost of servicing that customer, or it will always be dropped!\n", - "\"\"\"\n", - "# To add disjunctions just to the customers, make a list of non-depots.\n", - "non_depot = set(range(customers.number))\n", - "non_depot.difference_update(vehicles.starts)\n", - "non_depot.difference_update(vehicles.ends)\n", - "penalty = 400000 # The cost for dropping a node from the plan.\n", - "nodes = [routing.AddDisjunction([manager.NodeToIndex(c)], penalty) for c in non_depot]\n", + " print('The Objective Value is {0}'.format(assignment.ObjectiveValue()))\n", "\n", - "# This is how you would implement partial routes if you already knew part\n", - "# of a feasible solution for example:\n", - "# partial = np.random.choice(list(non_depot), size=(4,5), replace=False)\n", + " plan_output, dropped = vehicle_output_string(manager, routing, assignment)\n", + " print(plan_output)\n", + " print('dropped nodes: ' + ', '.join(dropped))\n", "\n", - "# routing.CloseModel()\n", - "# partial_list = [partial[0,:].tolist(),\n", - "# partial[1,:].tolist(),\n", - "# partial[2,:].tolist(),\n", - "# partial[3,:].tolist(),\n", - "# [],[],[],[]]\n", - "# print(routing.ApplyLocksToAllVehicles(partial_list, False))\n", + " # you could print debug information like this:\n", + " # print(routing.DebugOutputAssignment(assignment, 'Capacity'))\n", "\n", - "# Solve the problem !\n", - "assignment = routing.SolveWithParameters(parameters)\n", + " vehicle_routes = {}\n", + " for veh in range(vehicles.number):\n", + " vehicle_routes[veh] = build_vehicle_route(manager, routing, assignment,\n", + " customers, veh)\n", "\n", - "# The rest is all optional for saving, printing or plotting the solution.\n", - "if assignment:\n", - " ## save the assignment, (Google Protobuf format)\n", - " #save_file_base = os.path.realpath(__file__).split('.')[0]\n", - " #if routing.WriteAssignment(save_file_base + '_assignment.ass'):\n", - " # print('succesfully wrote assignment to file ' + save_file_base +\n", - " # '_assignment.ass')\n", + " # Plotting of the routes in matplotlib.\n", + " fig = plt.figure()\n", + " ax = fig.add_subplot(111)\n", + " # Plot all the nodes as black dots.\n", + " clon, clat = zip(*[(c.lon, c.lat) for c in customers.customers])\n", + " ax.plot(clon, clat, 'k.')\n", + " # plot the routes as arrows\n", + " plot_vehicle_routes(vehicle_routes, ax, customers, vehicles)\n", + " plt.show()\n", "\n", - " print('The Objective Value is {0}'.format(assignment.ObjectiveValue()))\n", + " else:\n", + " print('No assignment')\n", "\n", - " plan_output, dropped = vehicle_output_string(manager, routing, assignment)\n", - " print(plan_output)\n", - " print('dropped nodes: ' + ', '.join(dropped))\n", "\n", - " # you could print debug information like this:\n", - " # print(routing.DebugOutputAssignment(assignment, 'Capacity'))\n", - "\n", - " vehicle_routes = {}\n", - " for veh in range(vehicles.number):\n", - " vehicle_routes[veh] = build_vehicle_route(manager, routing, assignment,\n", - " customers, veh)\n", - "\n", - " # Plotting of the routes in matplotlib.\n", - " fig = plt.figure()\n", - " ax = fig.add_subplot(111)\n", - " # Plot all the nodes as black dots.\n", - " clon, clat = zip(*[(c.lon, c.lat) for c in customers.customers])\n", - " ax.plot(clon, clat, 'k.')\n", - " # plot the routes as arrows\n", - " plot_vehicle_routes(vehicle_routes, ax, customers, vehicles)\n", - " plt.show()\n", - "\n", - "else:\n", - " print('No assignment')\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/flexible_job_shop_sat.ipynb b/examples/notebook/examples/flexible_job_shop_sat.ipynb index f2ba513666..655c394d7b 100644 --- a/examples/notebook/examples/flexible_job_shop_sat.ipynb +++ b/examples/notebook/examples/flexible_job_shop_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Solves a flexible jobshop problems with the CP-SAT solver.\n", + "Solves a flexible jobshop problems with the CP-SAT solver.\n", "\n", "A jobshop is a standard scheduling problem when you must sequence a\n", "series of task_types on a set of machines. Each job contains one task_type per\n", @@ -96,11 +81,17 @@ "\n", "The objective is to minimize the maximum completion time of all\n", "jobs. This is called the makespan.\n", - "\"\"\"\n", - "\n", - "# overloaded sum() clashes with pytype.\n", - "# pytype: disable=wrong-arg-types\n", "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "import collections\n", "\n", "from ortools.sat.python import cp_model\n", diff --git a/examples/notebook/examples/gate_scheduling_sat.ipynb b/examples/notebook/examples/gate_scheduling_sat.ipynb index 0d17177079..3d2e599093 100644 --- a/examples/notebook/examples/gate_scheduling_sat.ipynb +++ b/examples/notebook/examples/gate_scheduling_sat.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"Gate Scheduling problem.\n", + "Gate Scheduling problem.\n", "\n", "We have a set of jobs to perform (duration, width).\n", "We have two parallel machines that can perform this job.\n", @@ -96,133 +81,143 @@ "exceed a max_width.\n", "\n", "The objective is to minimize the max end time of all jobs.\n", - "\"\"\"\n", - "\n", - "from absl import app\n", - "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.sat.python import visualization\n", "from ortools.sat.python import cp_model\n", "\n", "\n", - "\"\"\"Solves the gate scheduling problem.\"\"\"\n", - "model = cp_model.CpModel()\n", + "def main(_):\n", + " \"\"\"Solves the gate scheduling problem.\"\"\"\n", + " model = cp_model.CpModel()\n", "\n", - "jobs = [\n", - " [3, 3], # [duration, width]\n", - " [2, 5],\n", - " [1, 3],\n", - " [3, 7],\n", - " [7, 3],\n", - " [2, 2],\n", - " [2, 2],\n", - " [5, 5],\n", - " [10, 2],\n", - " [4, 3],\n", - " [2, 6],\n", - " [1, 2],\n", - " [6, 8],\n", - " [4, 5],\n", - " [3, 7]\n", - "]\n", + " jobs = [\n", + " [3, 3], # [duration, width]\n", + " [2, 5],\n", + " [1, 3],\n", + " [3, 7],\n", + " [7, 3],\n", + " [2, 2],\n", + " [2, 2],\n", + " [5, 5],\n", + " [10, 2],\n", + " [4, 3],\n", + " [2, 6],\n", + " [1, 2],\n", + " [6, 8],\n", + " [4, 5],\n", + " [3, 7]\n", + " ]\n", "\n", - "max_width = 10\n", + " max_width = 10\n", "\n", - "horizon = sum(t[0] for t in jobs)\n", - "num_jobs = len(jobs)\n", - "all_jobs = range(num_jobs)\n", + " horizon = sum(t[0] for t in jobs)\n", + " num_jobs = len(jobs)\n", + " all_jobs = range(num_jobs)\n", "\n", - "intervals = []\n", - "intervals0 = []\n", - "intervals1 = []\n", - "performed = []\n", - "starts = []\n", - "ends = []\n", - "demands = []\n", - "\n", - "for i in all_jobs:\n", - " # Create main interval.\n", - " start = model.NewIntVar(0, horizon, 'start_%i' % i)\n", - " duration = jobs[i][0]\n", - " end = model.NewIntVar(0, horizon, 'end_%i' % i)\n", - " interval = model.NewIntervalVar(start, duration, end, 'interval_%i' % i)\n", - " starts.append(start)\n", - " intervals.append(interval)\n", - " ends.append(end)\n", - " demands.append(jobs[i][1])\n", - "\n", - " # Create an optional copy of interval to be executed on machine 0.\n", - " performed_on_m0 = model.NewBoolVar('perform_%i_on_m0' % i)\n", - " performed.append(performed_on_m0)\n", - " start0 = model.NewIntVar(0, horizon, 'start_%i_on_m0' % i)\n", - " end0 = model.NewIntVar(0, horizon, 'end_%i_on_m0' % i)\n", - " interval0 = model.NewOptionalIntervalVar(start0, duration, end0,\n", - " performed_on_m0,\n", - " 'interval_%i_on_m0' % i)\n", - " intervals0.append(interval0)\n", - "\n", - " # Create an optional copy of interval to be executed on machine 1.\n", - " start1 = model.NewIntVar(0, horizon, 'start_%i_on_m1' % i)\n", - " end1 = model.NewIntVar(0, horizon, 'end_%i_on_m1' % i)\n", - " interval1 = model.NewOptionalIntervalVar(start1, duration, end1,\n", - " performed_on_m0.Not(),\n", - " 'interval_%i_on_m1' % i)\n", - " intervals1.append(interval1)\n", - "\n", - " # We only propagate the constraint if the tasks is performed on the machine.\n", - " model.Add(start0 == start).OnlyEnforceIf(performed_on_m0)\n", - " model.Add(start1 == start).OnlyEnforceIf(performed_on_m0.Not())\n", - "\n", - "# Width constraint (modeled as a cumulative)\n", - "model.AddCumulative(intervals, demands, max_width)\n", - "\n", - "# Choose which machine to perform the jobs on.\n", - "model.AddNoOverlap(intervals0)\n", - "model.AddNoOverlap(intervals1)\n", - "\n", - "# Objective variable.\n", - "makespan = model.NewIntVar(0, horizon, 'makespan')\n", - "model.AddMaxEquality(makespan, ends)\n", - "model.Minimize(makespan)\n", - "\n", - "# Symmetry breaking.\n", - "model.Add(performed[0] == 0)\n", - "\n", - "# Solve model.\n", - "solver = cp_model.CpSolver()\n", - "solver.Solve(model)\n", - "\n", - "# Output solution.\n", - "if visualization.RunFromIPython():\n", - " output = visualization.SvgWrapper(solver.ObjectiveValue(), max_width,\n", - " 40.0)\n", - " output.AddTitle('Makespan = %i' % solver.ObjectiveValue())\n", - " color_manager = visualization.ColorManager()\n", - " color_manager.SeedRandomColor(0)\n", + " intervals = []\n", + " intervals0 = []\n", + " intervals1 = []\n", + " performed = []\n", + " starts = []\n", + " ends = []\n", + " demands = []\n", "\n", " for i in all_jobs:\n", - " performed_machine = 1 - solver.Value(performed[i])\n", - " start = solver.Value(starts[i])\n", - " d_x = jobs[i][0]\n", - " d_y = jobs[i][1]\n", - " s_y = performed_machine * (max_width - d_y)\n", - " output.AddRectangle(start, s_y, d_x, d_y,\n", - " color_manager.RandomColor(), 'black', 'j%i' % i)\n", + " # Create main interval.\n", + " start = model.NewIntVar(0, horizon, 'start_%i' % i)\n", + " duration = jobs[i][0]\n", + " end = model.NewIntVar(0, horizon, 'end_%i' % i)\n", + " interval = model.NewIntervalVar(start, duration, end, 'interval_%i' % i)\n", + " starts.append(start)\n", + " intervals.append(interval)\n", + " ends.append(end)\n", + " demands.append(jobs[i][1])\n", "\n", - " output.AddXScale()\n", - " output.AddYScale()\n", - " output.Display()\n", - "else:\n", - " print('Solution')\n", - " print(' - makespan = %i' % solver.ObjectiveValue())\n", - " for i in all_jobs:\n", - " performed_machine = 1 - solver.Value(performed[i])\n", - " start = solver.Value(starts[i])\n", - " print(' - Job %i starts at %i on machine %i' %\n", - " (i, start, performed_machine))\n", - " print('Statistics')\n", - " print(' - conflicts : %i' % solver.NumConflicts())\n", - " print(' - branches : %i' % solver.NumBranches())\n", - " print(' - wall time : %f s' % solver.WallTime())\n", + " # Create an optional copy of interval to be executed on machine 0.\n", + " performed_on_m0 = model.NewBoolVar('perform_%i_on_m0' % i)\n", + " performed.append(performed_on_m0)\n", + " start0 = model.NewIntVar(0, horizon, 'start_%i_on_m0' % i)\n", + " end0 = model.NewIntVar(0, horizon, 'end_%i_on_m0' % i)\n", + " interval0 = model.NewOptionalIntervalVar(start0, duration, end0,\n", + " performed_on_m0,\n", + " 'interval_%i_on_m0' % i)\n", + " intervals0.append(interval0)\n", + "\n", + " # Create an optional copy of interval to be executed on machine 1.\n", + " start1 = model.NewIntVar(0, horizon, 'start_%i_on_m1' % i)\n", + " end1 = model.NewIntVar(0, horizon, 'end_%i_on_m1' % i)\n", + " interval1 = model.NewOptionalIntervalVar(start1, duration, end1,\n", + " performed_on_m0.Not(),\n", + " 'interval_%i_on_m1' % i)\n", + " intervals1.append(interval1)\n", + "\n", + " # We only propagate the constraint if the tasks is performed on the machine.\n", + " model.Add(start0 == start).OnlyEnforceIf(performed_on_m0)\n", + " model.Add(start1 == start).OnlyEnforceIf(performed_on_m0.Not())\n", + "\n", + " # Width constraint (modeled as a cumulative)\n", + " model.AddCumulative(intervals, demands, max_width)\n", + "\n", + " # Choose which machine to perform the jobs on.\n", + " model.AddNoOverlap(intervals0)\n", + " model.AddNoOverlap(intervals1)\n", + "\n", + " # Objective variable.\n", + " makespan = model.NewIntVar(0, horizon, 'makespan')\n", + " model.AddMaxEquality(makespan, ends)\n", + " model.Minimize(makespan)\n", + "\n", + " # Symmetry breaking.\n", + " model.Add(performed[0] == 0)\n", + "\n", + " # Solve model.\n", + " solver = cp_model.CpSolver()\n", + " solver.Solve(model)\n", + "\n", + " # Output solution.\n", + " if visualization.RunFromIPython():\n", + " output = visualization.SvgWrapper(solver.ObjectiveValue(), max_width,\n", + " 40.0)\n", + " output.AddTitle('Makespan = %i' % solver.ObjectiveValue())\n", + " color_manager = visualization.ColorManager()\n", + " color_manager.SeedRandomColor(0)\n", + "\n", + " for i in all_jobs:\n", + " performed_machine = 1 - solver.Value(performed[i])\n", + " start = solver.Value(starts[i])\n", + " d_x = jobs[i][0]\n", + " d_y = jobs[i][1]\n", + " s_y = performed_machine * (max_width - d_y)\n", + " output.AddRectangle(start, s_y, d_x, d_y,\n", + " color_manager.RandomColor(), 'black', 'j%i' % i)\n", + "\n", + " output.AddXScale()\n", + " output.AddYScale()\n", + " output.Display()\n", + " else:\n", + " print('Solution')\n", + " print(' - makespan = %i' % solver.ObjectiveValue())\n", + " for i in all_jobs:\n", + " performed_machine = 1 - solver.Value(performed[i])\n", + " start = solver.Value(starts[i])\n", + " print(' - Job %i starts at %i on machine %i' %\n", + " (i, start, performed_machine))\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", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/golomb8.ipynb b/examples/notebook/examples/golomb8.ipynb index 4f15986c89..1548229063 100644 --- a/examples/notebook/examples/golomb8.ipynb +++ b/examples/notebook/examples/golomb8.ipynb @@ -5,7 +5,7 @@ "id": "google", "metadata": {}, "source": [ - "##### Copyright 2021 Google LLC." + "##### Copyright 2022 Google LLC." ] }, { @@ -68,26 +68,11 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "code", + "cell_type": "markdown", + "id": "description", "metadata": {}, - "outputs": [], "source": [ - "#!/usr/bin/env python3\n", - "# Copyright 2010-2021 Google LLC\n", - "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", - "# you may not use this file except in compliance with the License.\n", - "# You may obtain a copy of the License at\n", - "#\n", - "# http://www.apache.org/licenses/LICENSE-2.0\n", - "#\n", - "# Unless required by applicable law or agreed to in writing, software\n", - "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", - "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", - "# See the License for the specific language governing permissions and\n", - "# limitations under the License.\n", - "\"\"\"This is the Golomb ruler problem.\n", + "This is the Golomb ruler problem.\n", "\n", "This model aims at maximizing radar interferences in a minimum space.\n", "It is known as the Golomb Ruler problem.\n", @@ -95,62 +80,91 @@ "The idea is to put marks on a rule such that all differences\n", "between all marks are all different. The objective is to minimize the length\n", "of the rule.\n", - "\"\"\"\n", - "\n", - "from absl import app\n", - "from absl import flags\n", + "see: https://en.wikipedia.org/wiki/Golomb_ruler\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "code", + "metadata": {}, + "outputs": [], + "source": [ "from ortools.constraint_solver import pywrapcp\n", "\n", - "FLAGS = flags.FLAGS\n", + "class FLAGS: pass\n", "\n", - "# We disable the following warning because it is a false positive on constraints\n", - "# like: solver.Add(x == 0)\n", - "# pylint: disable=g-explicit-bool-comparison\n", + "FLAGS.order = 8 # Order of the ruler.\n", + "\n", + "def solve_golomb_ruler(order):\n", + " # Create the solver.\n", + " solver = pywrapcp.Solver('golomb ruler')\n", + "\n", + " var_max = order * order\n", + " all_vars = list(range(0, order))\n", + "\n", + " marks = [solver.IntVar(0, var_max, f'marks_{i}') for i in all_vars]\n", + "\n", + " solver.Add(marks[0] == 0)\n", + " for i in range(order - 2):\n", + " solver.Add(marks[i + 1] > marks[i])\n", + "\n", + " # We expand the creation of the diff array to avoid a pylint warning.\n", + " diffs = []\n", + " for i in range(order - 1):\n", + " for j in range(i + 1, order):\n", + " diffs.append(marks[j] - marks[i])\n", + " solver.Add(solver.AllDifferent(diffs))\n", + "\n", + " # symmetry breaking\n", + " if order > 2:\n", + " solver.Add(marks[order - 1] - marks[order - 2] > marks[1] - marks[0])\n", + "\n", + " # objective\n", + " objective = solver.Minimize(marks[order - 1], 1)\n", + "\n", + " # Solve the model.\n", + " solution = solver.Assignment()\n", + " for mark in marks:\n", + " solution.Add(mark)\n", + " for diff in diffs:\n", + " solution.Add(diff)\n", + " collector = solver.AllSolutionCollector(solution)\n", + "\n", + " solver.Solve(\n", + " solver.Phase(\n", + " marks,\n", + " solver.CHOOSE_FIRST_UNBOUND,\n", + " solver.ASSIGN_MIN_VALUE),\n", + " [objective, collector])\n", + "\n", + " # Print solution.\n", + " for i in range(0, collector.SolutionCount()):\n", + " obj_value = collector.Value(i, marks[order - 1])\n", + " print(f'Solution #{i}: value = {obj_value}')\n", + " for idx, var in enumerate(marks):\n", + " print(f'mark[{idx}]: {collector.Value(i, var)}')\n", + " intervals = [collector.Value(i, diff) for diff in diffs]\n", + " intervals.sort()\n", + " print(f'intervals: {intervals}')\n", + "\n", + " print('Statistics:')\n", + " print(f'- conflicts: {collector.Failures(i)}')\n", + " print(f'- branches : {collector.Branches(i)}')\n", + " print(f'- wall time: {collector.WallTime(i)}ms\\n')\n", + "\n", + " print('Global Statistics:')\n", + " print(f'- total conflicts: {solver.Failures()}')\n", + " print(f'- total branches : {solver.Branches()}')\n", + " print(f'- total wall time: {solver.WallTime()}ms\\n')\n", "\n", "\n", - "# Create the solver.\n", - "solver = pywrapcp.Solver('golomb ruler')\n", + "def main(_):\n", + " solve_golomb_ruler(FLAGS.order)\n", "\n", - "size = 8\n", - "var_max = size * size\n", - "all_vars = list(range(0, size))\n", "\n", - "marks = [solver.IntVar(0, var_max, 'marks_%d' % i) for i in all_vars]\n", - "\n", - "objective = solver.Minimize(marks[size - 1], 1)\n", - "\n", - "solver.Add(marks[0] == 0)\n", - "\n", - "# We expand the creation of the diff array to avoid a pylint warning.\n", - "diffs = []\n", - "for i in range(size - 1):\n", - " for j in range(i + 1, size):\n", - " diffs.append(marks[j] - marks[i])\n", - "solver.Add(solver.AllDifferent(diffs))\n", - "\n", - "solver.Add(marks[size - 1] - marks[size - 2] > marks[1] - marks[0])\n", - "for i in range(size - 2):\n", - " solver.Add(marks[i + 1] > marks[i])\n", - "\n", - "solution = solver.Assignment()\n", - "solution.Add(marks[size - 1])\n", - "collector = solver.AllSolutionCollector(solution)\n", - "\n", - "solver.Solve(\n", - " solver.Phase(marks, solver.CHOOSE_FIRST_UNBOUND,\n", - " solver.ASSIGN_MIN_VALUE), [objective, collector])\n", - "for i in range(0, collector.SolutionCount()):\n", - " obj_value = collector.Value(i, marks[size - 1])\n", - " time = collector.WallTime(i)\n", - " branches = collector.Branches(i)\n", - " failures = collector.Failures(i)\n", - " print(('Solution #%i: value = %i, failures = %i, branches = %i,'\n", - " 'time = %i ms') % (i, obj_value, failures, branches, time))\n", - "time = solver.WallTime()\n", - "branches = solver.Branches()\n", - "failures = solver.Failures()\n", - "print(('Total run : failures = %i, branches = %i, time = %i ms' %\n", - " (failures, branches, time)))\n", + "main()\n", "\n" ] } diff --git a/examples/notebook/examples/golomb_sat.ipynb b/examples/notebook/examples/golomb_sat.ipynb new file mode 100644 index 0000000000..bf11a3bf17 --- /dev/null +++ b/examples/notebook/examples/golomb_sat.ipynb @@ -0,0 +1,165 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "google", + "metadata": {}, + "source": [ + "##### Copyright 2022 Google LLC." + ] + }, + { + "cell_type": "markdown", + "id": "apache", + "metadata": {}, + "source": [ + "Licensed under the Apache License, Version 2.0 (the \"License\");\n", + "you may not use this file except in compliance with the License.\n", + "You may obtain a copy of the License at\n", + "\n", + " http://www.apache.org/licenses/LICENSE-2.0\n", + "\n", + "Unless required by applicable law or agreed to in writing, software\n", + "distributed under the License is distributed on an \"AS IS\" BASIS,\n", + "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", + "See the License for the specific language governing permissions and\n", + "limitations under the License.\n" + ] + }, + { + "cell_type": "markdown", + "id": "basename", + "metadata": {}, + "source": [ + "# golomb_sat" + ] + }, + { + "cell_type": "markdown", + "id": "link", + "metadata": {}, + "source": [ + "
\n",
+ " Run in Google Colab\n",
+ " | \n",
+ "\n",
+ " View source on GitHub\n",
+ " | \n",
+ "