add ipython notebooks
This commit is contained in:
237
examples/notebook/code_samples_sat.ipynb
Normal file
237
examples/notebook/code_samples_sat.ipynb
Normal file
@@ -0,0 +1,237 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2017 Google\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"\n",
|
||||
"import collections\n",
|
||||
"\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSat():\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"# Creates the variables.\n",
|
||||
" num_vals = 3\n",
|
||||
" x = model.NewIntVar(0, num_vals - 1, \"x\")\n",
|
||||
" y = model.NewIntVar(0, num_vals - 1, \"y\")\n",
|
||||
" z = model.NewIntVar(0, num_vals - 1, \"z\")\n",
|
||||
" # Create the constraints.\n",
|
||||
" model.Add(x != y)\n",
|
||||
"\n",
|
||||
" # Create a solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.MODEL_SAT:\n",
|
||||
" print(\"x = %i\" % solver.Value(x))\n",
|
||||
" print(\"y = %i\" % solver.Value(y))\n",
|
||||
" print(\"z = %i\" % solver.Value(z))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class VarArraySolutionPrinter(cp_model.CpSolverSolutionCallback):\n",
|
||||
" \"\"\"Print intermediate solutions.\"\"\"\n",
|
||||
"\n",
|
||||
" def __init__(self, variables):\n",
|
||||
" self.__variables = variables\n",
|
||||
" self.__solution_count = 0\n",
|
||||
"\n",
|
||||
" def NewSolution(self):\n",
|
||||
" self.__solution_count += 1\n",
|
||||
" for v in self.__variables:\n",
|
||||
" print('%s=%i' % (v, self.Value(v)), end = ' ')\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" def SolutionCount(self):\n",
|
||||
" return self.__solution_count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalCpSatAllSolutions():\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"# Creates the variables.\n",
|
||||
" num_vals = 3\n",
|
||||
" x = model.NewIntVar(0, num_vals - 1, \"x\")\n",
|
||||
" y = model.NewIntVar(0, num_vals - 1, \"y\")\n",
|
||||
" z = model.NewIntVar(0, num_vals - 1, \"z\")\n",
|
||||
" # Create the constraints.\n",
|
||||
" model.Add(x != y)\n",
|
||||
"\n",
|
||||
" # Create a solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" solution_printer = VarArraySolutionPrinter([x, y, z])\n",
|
||||
" status = solver.SearchForAllSolutions(model, solution_printer)\n",
|
||||
"\n",
|
||||
" print('Number of solutions found: %i' % solution_printer.SolutionCount())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def SolvingLinearProblem():\n",
|
||||
" # Create a model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" # x and y are integer non-negative variables.\n",
|
||||
" x = model.NewIntVar(0, 17, 'x')\n",
|
||||
" y = model.NewIntVar(0, 17, 'y')\n",
|
||||
" model.Add(2*x + 14*y <= 35)\n",
|
||||
" model.Add(2*x <= 7)\n",
|
||||
" obj_var = model.NewIntVar(0, 1000, \"obj_var\")\n",
|
||||
" model.Add(obj_var == x + 10*y)\n",
|
||||
" objective = model.Maximize(obj_var)\n",
|
||||
"\n",
|
||||
" # Create a solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" print(\"Objective value: %i\" % solver.ObjectiveValue())\n",
|
||||
" print()\n",
|
||||
" print('x= %i' % solver.Value(x))\n",
|
||||
" print('y= %i' % solver.Value(y))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def MinimalJobShop():\n",
|
||||
" # Create the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" machines_count = 3\n",
|
||||
" jobs_count = 3\n",
|
||||
" all_machines = range(0, machines_count)\n",
|
||||
" all_jobs = range(0, jobs_count)\n",
|
||||
" # Define data.\n",
|
||||
" machines = [[0, 1, 2],\n",
|
||||
" [0, 2, 1],\n",
|
||||
" [1, 2]]\n",
|
||||
"\n",
|
||||
" processing_times = [[3, 2, 2],\n",
|
||||
" [2, 1, 4],\n",
|
||||
" [4, 3]]\n",
|
||||
" # Computes horizon.\n",
|
||||
" horizon = 0\n",
|
||||
" for job in all_jobs:\n",
|
||||
" horizon += sum(processing_times[job])\n",
|
||||
"\n",
|
||||
" Task = collections.namedtuple('Task', 'start end interval')\n",
|
||||
" AssignedTask = collections.namedtuple('AssignedTask', 'start job index')\n",
|
||||
"\n",
|
||||
" # Creates jobs.\n",
|
||||
" all_tasks = {}\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job])):\n",
|
||||
" start_var = model.NewIntVar(0, horizon, 'start_%i_%i' % (job, index))\n",
|
||||
" duration = processing_times[job][index]\n",
|
||||
" end_var = model.NewIntVar(0, horizon, 'end_%i_%i' % (job, index))\n",
|
||||
" interval_var = model.NewIntervalVar(start_var, duration, end_var,\n",
|
||||
" 'interval_%i_%i' % (job, index))\n",
|
||||
" all_tasks[(job, index)] = Task(start=start_var,\n",
|
||||
" end=end_var,\n",
|
||||
" interval=interval_var)\n",
|
||||
"\n",
|
||||
" # Creates sequence variables and add disjunctive constraints.\n",
|
||||
" for machine in all_machines:\n",
|
||||
" intervals = []\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job])):\n",
|
||||
" if machines[job][index] == machine:\n",
|
||||
" intervals.append(all_tasks[(job, index)].interval)\n",
|
||||
" model.AddNoOverlap(intervals)\n",
|
||||
"\n",
|
||||
" # Add precedence contraints.\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(0, len(machines[job]) - 1):\n",
|
||||
" model.Add(all_tasks[(job, index + 1)].start >=\n",
|
||||
" all_tasks[(job, index)].end)\n",
|
||||
"\n",
|
||||
" # Makespan objective.\n",
|
||||
" obj_var = model.NewIntVar(0, horizon, 'makespan')\n",
|
||||
" model.AddMaxEquality(\n",
|
||||
" obj_var, [all_tasks[(job, len(machines[job]) - 1)].end\n",
|
||||
" for job in all_jobs])\n",
|
||||
" model.Minimize(obj_var)\n",
|
||||
"\n",
|
||||
" # Solve model.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" status = solver.Solve(model)\n",
|
||||
"\n",
|
||||
" if status == cp_model.OPTIMAL:\n",
|
||||
" # Print out makespan.\n",
|
||||
" print('Optimal Schedule Length: %i' % solver.ObjectiveValue())\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" # Create one list of assigned tasks per machine.\n",
|
||||
" assigned_jobs = [[] for _ in range(machines_count)]\n",
|
||||
" for job in all_jobs:\n",
|
||||
" for index in range(len(machines[job])):\n",
|
||||
" machine = machines[job][index]\n",
|
||||
" assigned_jobs[machine].append(\n",
|
||||
" AssignedTask(start = solver.Value(all_tasks[(job, index)].start),\n",
|
||||
" job = job, index = index))\n",
|
||||
"\n",
|
||||
" disp_col_width = 10\n",
|
||||
" sol_line = \"\"\n",
|
||||
" sol_line_tasks = \"\"\n",
|
||||
"\n",
|
||||
" print(\"Optimal Schedule\", \"\\n\")\n",
|
||||
"\n",
|
||||
" for machine in all_machines:\n",
|
||||
" # Sort by starting time.\n",
|
||||
" assigned_jobs[machine].sort()\n",
|
||||
" sol_line += \"Machine \" + str(machine) + \": \"\n",
|
||||
" sol_line_tasks += \"Machine \" + str(machine) + \": \"\n",
|
||||
"\n",
|
||||
" for assigned_task in assigned_jobs[machine]:\n",
|
||||
" name = 'job_%i_%i' % (assigned_task.job, assigned_task.index)\n",
|
||||
" # Add spaces to output to align columns.\n",
|
||||
" sol_line_tasks += name + \" \" * (disp_col_width - len(name))\n",
|
||||
" start = assigned_task.start\n",
|
||||
" duration = processing_times[assigned_task.job][assigned_task.index]\n",
|
||||
"\n",
|
||||
" sol_tmp = \"[%i,%i]\" % (start, start + duration)\n",
|
||||
" # Add spaces to output to align columns.\n",
|
||||
" sol_line += sol_tmp + \" \" * (disp_col_width - len(sol_tmp))\n",
|
||||
"\n",
|
||||
" sol_line += \"\\n\"\n",
|
||||
" sol_line_tasks += \"\\n\"\n",
|
||||
"\n",
|
||||
" print(sol_line_tasks)\n",
|
||||
" print(\"Time Intervals for Tasks\\n\")\n",
|
||||
" print(sol_line)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" MinimalCpSat()\n",
|
||||
" MinimalCpSatAllSolutions()\n",
|
||||
" SolvingLinearProblem()\n",
|
||||
" MinimalJobShop()\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == '__main__':\n",
|
||||
" main()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
148
examples/notebook/nurses_sat.ipynb
Normal file
148
examples/notebook/nurses_sat.ipynb
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Copyright 2010-2017 Google\n",
|
||||
"# Licensed under the Apache License, Version 2.0 (the \"License\");\n",
|
||||
"# you may not use this file except in compliance with the License.\n",
|
||||
"# You may obtain a copy of the License at\n",
|
||||
"#\n",
|
||||
"# http://www.apache.org/licenses/LICENSE-2.0\n",
|
||||
"#\n",
|
||||
"# Unless required by applicable law or agreed to in writing, software\n",
|
||||
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
|
||||
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
|
||||
"# See the License for the specific language governing permissions and\n",
|
||||
"# limitations under the License.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"from __future__ import print_function\n",
|
||||
"import sys\n",
|
||||
"from ortools.sat.python import cp_model\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"class NursesPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):\n",
|
||||
" \"\"\"Print intermediate solutions.\"\"\"\n",
|
||||
"\n",
|
||||
" def __init__(self, shifts, num_nurses, num_days, num_shifts, sols):\n",
|
||||
" self.__shifts = shifts\n",
|
||||
" self.__num_nurses = num_nurses\n",
|
||||
" self.__num_days = num_days\n",
|
||||
" self.__num_shifts = num_shifts\n",
|
||||
" self.__solutions = set(sols)\n",
|
||||
" self.__solution_count = 0\n",
|
||||
"\n",
|
||||
" def NewSolution(self):\n",
|
||||
" self.__solution_count += 1\n",
|
||||
" if self.__solution_count in self.__solutions:\n",
|
||||
" print('Solution #%i' % self.__solution_count)\n",
|
||||
" for d in range(self.__num_days):\n",
|
||||
" print('Day #%i' % d)\n",
|
||||
" for n in range(self.__num_nurses):\n",
|
||||
" for s in range(self.__num_shifts):\n",
|
||||
" if self.Value(self.__shifts[(n, d, s)]):\n",
|
||||
" print(' Nurse #%i is working shift #%i' % (n, s))\n",
|
||||
" print()\n",
|
||||
"\n",
|
||||
" def SolutionCount(self):\n",
|
||||
" return self.__solution_count\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def main():\n",
|
||||
" # Data.\n",
|
||||
" num_nurses = 4\n",
|
||||
" num_shifts = 4 # Nurse assigned to shift 0 means not working that day.\n",
|
||||
" num_days = 7\n",
|
||||
" all_nurses = range(num_nurses)\n",
|
||||
" all_shifts = range(num_shifts)\n",
|
||||
" all_working_shifts = range(1, num_shifts)\n",
|
||||
" all_days = range(num_days)\n",
|
||||
"\n",
|
||||
" # Creates the model.\n",
|
||||
" model = cp_model.CpModel()\n",
|
||||
"\n",
|
||||
" # Creates shift variables.\n",
|
||||
" # shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.\n",
|
||||
" shifts = {}\n",
|
||||
" for n in all_nurses:\n",
|
||||
" for d in all_days:\n",
|
||||
" for s in all_shifts:\n",
|
||||
" shifts[(n, d, s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))\n",
|
||||
"\n",
|
||||
" # Makes assignments different on each day, that is each shift is assigned at\n",
|
||||
" # most one nurse. As we have the same number of nurses and shifts, then each\n",
|
||||
" # day, each shift is assigned to exactly one nurse.\n",
|
||||
" for d in all_days:\n",
|
||||
" for s in all_shifts:\n",
|
||||
" model.Add(sum(shifts[(n, d, s)] for n in all_nurses) == 1)\n",
|
||||
"\n",
|
||||
" # Nurses do 1 shift per day.\n",
|
||||
" for n in all_nurses:\n",
|
||||
" for d in all_days:\n",
|
||||
" model.Add(sum(shifts[(n, d, s)] for s in all_shifts) == 1)\n",
|
||||
"\n",
|
||||
" # Each nurse works 5 or 6 days in a week.\n",
|
||||
" # That is each nurse works shift 0 at most 2 times.\n",
|
||||
" for n in all_nurses:\n",
|
||||
" model.AddSumConstraint([shifts[(n, d, 0)] for d in all_days], 1, 2)\n",
|
||||
"\n",
|
||||
" # works_shift[(n, s)] is 1 if nurse n works shift s at least one day in\n",
|
||||
" # the week.\n",
|
||||
" works_shift = {}\n",
|
||||
" for n in all_nurses:\n",
|
||||
" for s in all_shifts:\n",
|
||||
" works_shift[(n, s)] = model.NewBoolVar('works_shift_n%is%i' % (n, s))\n",
|
||||
" model.AddMaxEquality(works_shift[(n, s)],\n",
|
||||
" [shifts[(n, d, s)] for d in all_days])\n",
|
||||
"\n",
|
||||
" # For each shift, at most 2 nurses are assigned to that shift during the week.\n",
|
||||
" for s in all_working_shifts:\n",
|
||||
" model.Add(sum(works_shift[(n, s)] for n in all_nurses) <= 2)\n",
|
||||
"\n",
|
||||
" # If s nurses works shifts 2 or 3 on, she must also work that shift the\n",
|
||||
" # previous day or the following day.\n",
|
||||
" # This means that on a given day and shift, either she does not work that\n",
|
||||
" # shift on that day, or she works that shift on the day before, or the day\n",
|
||||
" # after.\n",
|
||||
" for n in all_nurses:\n",
|
||||
" for s in [2, 3]:\n",
|
||||
" for d in all_days:\n",
|
||||
" yesterday = (d - 1) % num_days\n",
|
||||
" tomorrow = (d + 1) % num_days\n",
|
||||
" model.AddBoolOr([shifts[(n, yesterday, s)], shifts[(n, d, s)].Not(),\n",
|
||||
" shifts[(n, tomorrow, s)]])\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" # Creates the solver and solve.\n",
|
||||
" solver = cp_model.CpSolver()\n",
|
||||
" # Display a few solutions picked at random.\n",
|
||||
" a_few_solutions = [859, 2034, 5091, 7003]\n",
|
||||
" solution_printer = NursesPartialSolutionPrinter(shifts, num_nurses,\n",
|
||||
" num_days, num_shifts,\n",
|
||||
" a_few_solutions)\n",
|
||||
" status = solver.SearchForAllSolutions(model, solution_printer)\n",
|
||||
"\n",
|
||||
" # Statistics.\n",
|
||||
" print()\n",
|
||||
" print('Statistics')\n",
|
||||
" print(' - conflicts : %i' % solver.NumConflicts())\n",
|
||||
" print(' - branches : %i' % solver.NumBranches())\n",
|
||||
" print(' - wall time : %f ms' % solver.WallTime())\n",
|
||||
" print(' - solutions found : %i' % solution_printer.SolutionCount())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"if __name__ == \"__main__\":\n",
|
||||
" main()"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
Reference in New Issue
Block a user