import%20marimo%0A%0A__generated_with%20%3D%20%220.14.7%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20ortools.sat.python%20import%20cp_model%0A%20%20%20%20return%20(cp_model%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%20%E7%9C%8B%E8%AD%B7%E5%B8%AB%E3%82%B9%E3%82%B1%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0%E5%95%8F%E9%A1%8C%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20%E5%95%8F%E9%A1%8C%E8%A8%AD%E5%AE%9A%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%E5%85%B8%E5%9E%8B%E7%9A%84%E3%81%AA%E8%A8%AD%E5%AE%9A%E3%81%A0%E3%81%A8%E4%B8%8B%E8%A8%98.%20%0A%0A%20%20%20%20-%20%E6%AF%8E%E6%97%A5%E3%81%AE%E5%90%84%E5%8B%A4%E5%8B%99%20(%E6%98%BC%2C%20%E5%A4%95%2C%20%E5%A4%9C)%20%E3%81%AE%E5%BF%85%E8%A6%81%E4%BA%BA%E6%95%B0%0A%20%20%20%20-%20%E5%90%84%E7%9C%8B%E8%AD%B7%E5%B8%AB%E3%81%AB%E5%AF%BE%E3%81%97%E3%81%A6%2030%20%E6%97%A5%E9%96%93%E3%81%AE%E5%8B%A4%E5%8B%99%E6%97%A5%E6%95%B0%E3%81%AE%E4%B8%8A%E4%B8%8B%E9%99%90%0A%20%20%20%20-%20%E6%8C%87%E5%AE%9A%E4%BC%91%E6%97%A5%2C%20%E6%8C%87%E5%AE%9A%E4%BC%9A%E8%AD%B0%E6%97%A5%0A%20%20%20%20-%20%E9%80%A3%E7%B6%9A%207%20%E6%97%A5%E9%96%93%E3%81%AB%E6%9C%80%E4%BD%8E%201%20%E6%97%A5%E3%81%AE%E4%BC%91%E6%97%A5%2C%20%E6%9C%80%E4%BD%8E%201%20%E6%97%A5%E3%81%AE%E6%98%BC%E5%8B%A4%E5%8B%99%0A%20%20%20%20-%20%E7%A6%81%E6%AD%A2%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%0A%20%20%20%20%20%20%20%20-%203%20%E9%80%A3%E7%B6%9A%E5%A4%9C%E5%8B%A4%0A%20%20%20%20%20%20%20%20-%204%20%E9%80%A3%E7%B6%9A%E5%A4%95%E5%8B%A4%0A%20%20%20%20%20%20%20%20-%205%20%E9%80%A3%E7%B6%9A%E6%98%BC%E5%8B%A4%0A%20%20%20%20%20%20%20%20-%20%E5%A4%9C%E5%8B%A4%E6%98%8E%E3%81%91%E3%81%AE%E4%BC%91%E6%97%A5%E4%BB%A5%E5%A4%96%0A%20%20%20%20%20%20%20%20-%20%E5%A4%95%E5%8B%A4%E3%81%AE%E7%9B%B4%E5%BE%8C%E3%81%AE%E6%98%BC%E5%8B%A4%E3%81%82%E3%82%8B%E3%81%84%E3%81%AF%E4%BC%9A%E8%AD%B0%0A%20%20%20%20%20%20%20%20-%20%E4%BC%91%E6%97%A5%20%3A%3Alucide%3Aarrow-right%3A%3A%20%E5%8B%A4%E5%8B%99%20%3A%3Alucide%3Aarrow-right%3A%3A%20%E4%BC%91%E6%97%A5%0A%20%20%20%20-%20%E5%A4%9C%E5%8B%A4%E3%81%AF%202%20%E5%9B%9E%E9%80%A3%E7%B6%9A%E3%81%A7%E8%A1%8C%E3%81%86%0A%20%20%20%20-%202%20%E3%81%A4%E3%81%AE%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AE%E4%BA%BA%E6%95%B0%E3%82%92%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%A0%E3%81%91%E5%9D%87%E7%AD%89%E5%8C%96%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%23%20%E5%AE%9A%E6%95%B0%0A%0A%20%20%20%20-%20%24W%24%3A%20%E4%BC%91%E6%97%A5%E4%BB%A5%E5%A4%96%E3%81%AE%E3%82%B7%E3%83%95%E3%83%88%E3%81%AE%E9%9B%86%E5%90%88%0A%20%20%20%20-%20%24N%24%3A%20%E5%A4%9C%E5%8B%A4%E4%BB%A5%E5%A4%96%E3%81%AE%E3%82%B7%E3%83%95%E3%83%88%E3%81%AE%E9%9B%86%E5%90%88%0A%20%20%20%20-%20%24L_%7Bd%20s%7D%24%3A%20%E6%97%A5%20%24d%24%20%E3%81%AE%E3%82%B7%E3%83%95%E3%83%88%20%24s%24%20%E3%81%AE%E5%BF%85%E8%A6%81%E4%BA%BA%E6%95%B0%0A%20%20%20%20-%20%24%5Cmathrm%7BLB%7D%2C%20%5Cmathrm%7BUB%7D%24%3A%20%E5%90%84%E7%9C%8B%E8%AD%B7%E5%B8%AB%E3%81%AE%2030%20%E6%97%A5%E9%96%93%E3%81%AE%E5%8B%A4%E5%8B%99%E6%97%A5%E6%95%B0%E3%81%AE%E4%B8%8A%E4%B8%8B%E9%99%90%0A%20%20%20%20-%20%24R_i%24%3A%20%E7%9C%8B%E8%AD%B7%E5%B8%AB%20%24i%24%20%E3%81%8C%E4%BC%91%E6%97%A5%E3%82%92%E5%B8%8C%E6%9C%9B%E3%81%99%E3%82%8B%E6%97%A5%E3%81%AE%E9%9B%86%E5%90%88%0A%20%20%20%20-%20%24T_1%2C%20T_2%24%3A%20%E3%83%81%E3%83%BC%E3%83%A0%201%2C%20%E3%83%81%E3%83%BC%E3%83%A0%202.%0A%0A%20%20%20%20%23%23%23%20%E6%B1%BA%E5%AE%9A%E5%A4%89%E6%95%B0%0A%0A%20%20%20%20-%20%24x_%7Bi%20d%20s%7D%24%3A%20%E7%9C%8B%E8%AD%B7%E5%B8%AB%20%24i%24%20%E3%81%AE%20%24d%24%20%E6%97%A5%E3%81%AE%E5%8B%A4%E5%8B%99%E3%81%8C%20%24s%24%20%E3%81%A7%E3%81%82%E3%82%8B%E3%81%A8%E3%81%8D%20%241%24.%20%E3%81%9D%E3%81%86%E3%81%A7%E3%81%AA%E3%81%84%E3%81%A8%E3%81%8D%20%240%24%0A%0A%20%20%20%20%23%23%23%20%E5%88%B6%E7%B4%84%E6%9D%A1%E4%BB%B6%0A%0A%20%20%20%20-%20%E6%AF%8E%E6%97%A5%E3%81%AE%E5%90%84%E5%8B%A4%E5%8B%99%E3%81%AE%E5%BF%85%E8%A6%81%E4%BA%BA%E6%95%B0%3A%20%24%5Csum_%7Bi%7D%20x_%7Bi%20d%20s%7D%20%5Cgeq%20L_%7Bd%20s%7D%24%20%24(%5Cforall%20d%2C%20s)%24%0A%20%20%20%20-%20%E5%90%84%E7%9C%8B%E8%AD%B7%E5%B8%AB%E3%81%AE%2030%20%E6%97%A5%E9%96%93%E3%81%AE%E5%8B%A4%E5%8B%99%E6%97%A5%E6%95%B0%E3%81%AE%E4%B8%8A%E4%B8%8B%E9%99%90%3A%20%24%5Cmathrm%7BLB%7D%20%5Cleq%20%5Csum_%7Bd%2C%20s%20%5Cin%20W%7D%20x_%7Bi%20d%20s%7D%20%5Cleq%20%5Cmathrm%7BUB%7D%24%20%24(%5Cforall%20i)%24%0A%20%20%20%20-%20%E6%8C%87%E5%AE%9A%E4%BC%91%E6%97%A5%E3%83%BB%E6%8C%87%E5%AE%9A%E4%BC%9A%E8%AD%B0%E6%97%A5%3A%20%24%5Csum_%7Bd%20%5Cin%20R_i%2C%20s%20%5Cin%20W%7D%20x_%7Bi%20d%20s%7D%20%5Cleq%200%24%20%24(%5Cforall%20i)%24%0A%20%20%20%20-%20%E9%80%A3%E7%B6%9A%207%20%E6%97%A5%E9%96%93%E3%81%AB%E6%9C%80%E4%BD%8E%201%20%E6%97%A5%E3%81%AE%E4%BC%91%E6%97%A5%2C%20%E6%9C%80%E4%BD%8E%201%20%E6%97%A5%E3%81%AE%E6%98%BC%E5%8B%A4%3A%0A%20%20%20%20%20%20%20%20-%20%24%5Csum_%7Bt%20%3D%200%7D%5E%7B6%7D%20x_%7Bi%2C%20d%2Bt%2C%20%5Ctext%7B%E4%BC%91%7D%7D%20%5Cgeq%201%24%20%24(%5Cforall%20i%2C%20d)%24%0A%20%20%20%20%20%20%20%20-%20%24%5Csum_%7Bt%20%3D%200%7D%5E%7B6%7D%20x_%7Bi%2C%20d%2Bt%2C%20%5Ctext%7B%E6%98%BC%7D%7D%20%5Cgeq%201%24%20%24(%5Cforall%20i%2C%20d)%24%0A%20%20%20%20-%20%E7%A6%81%E6%AD%A2%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%0A%20%20%20%20%20%20%20%20-%203%20%E9%80%A3%E7%B6%9A%E5%A4%9C%E5%8B%A4%3A%20%24%5Csum_%7Bt%20%3D%200%7D%5E%7B2%7D%20x_%7Bi%2C%20d%2Bt%2C%20%5Ctext%7B%E5%A4%9C%7D%7D%20%5Cleq%202%24%20%24(%5Cforall%20i%2C%20d)%24%0A%20%20%20%20%20%20%20%20-%204%20%E9%80%A3%E7%B6%9A%E5%A4%95%E5%8B%A4%3A%20%24%5Csum_%7Bt%20%3D%200%7D%5E%7B3%7D%20x_%7Bi%2C%20d%2Bt%2C%20%5Ctext%7B%E5%A4%95%7D%7D%20%5Cleq%203%24%20%24(%5Cforall%20i%2C%20d)%24%0A%20%20%20%20%20%20%20%20-%205%20%E9%80%A3%E7%B6%9A%E6%98%BC%E5%8B%A4%3A%20%24%5Csum_%7Bt%20%3D%200%7D%5E%7B4%7D%20x_%7Bi%2C%20d%2Bt%2C%20%5Ctext%7B%E6%98%BC%7D%7D%20%5Cleq%204%24%20%24(%5Cforall%20i%2C%20d)%24%0A%20%20%20%20%20%20%20%20-%20%E5%A4%9C%E5%8B%A4%E6%98%8E%E3%81%91%E3%81%AE%E4%BC%91%E6%97%A5%E4%BB%A5%E5%A4%96%3A%20%24%5Csum_%7Bs%20%5Cin%20W%20%5Ccap%20N%7D%20x_%7Bi%2C%20d%20%2B%201%2C%20s%7D%20%3C%3D%205%20%5Ccdot%20(1%20-%20x_%7Bi%2C%20d%2C%20%5Ctext%7B%E5%A4%9C%7D%7D)%24%0A%20%20%20%20%20%20%20%20-%20%E5%A4%95%E3%81%AE%E7%9B%B4%E5%BE%8C%E3%81%AE%E6%98%BC%E3%81%82%E3%82%8B%E3%81%84%E3%81%AF%E4%BC%9A%E8%AD%B0%3A%20%E4%BC%9A%E8%AD%B0%E3%81%8C%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7%E7%9C%81%E7%95%A5%0A%20%20%20%20%20%20%20%20-%20%E4%BC%91%E6%97%A5%20%3A%3Alucide%3Aarrow-right%3A%3A%20%E5%8B%A4%E5%8B%99%20%3A%3Alucide%3Aarrow-right%3A%3A%20%E4%BC%91%E6%97%A5%3A%20%24x_%7Bi%2C%20d-1%2C%20%5Ctext%7B%E4%BC%91%7D%7D%20%2B%20%5Csum_%7Bs%20%5Cin%20W%7D%20x_%7Bi%20d%20s%7D%20%2B%20x_%7Bi%2C%20d%2B1%2C%20%5Ctext%7B%E4%BC%91%7D%7D%20%5Cleq%202%24%0A%20%20%20%20-%20%E5%A4%9C%E5%8B%A4%E3%81%AF%202%20%E9%80%A3%E7%B6%9A%3A%20%24%5Csum_%7Bs%20%5Cin%20N%7D%20x_%7Bi%2Cd-1%2Cs%7D%20%2B%20x_%7Bi%2Cd%2C%5Ctext%7B%E5%A4%9C%7D%7D%20%2B%20%5Csum_%7Bs%20%5Cin%20N%7D%20x_%7Bi%2Cd%2B1%2Cs%7D%20%5Cleq%202%24%0A%20%20%20%20-%202%20%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AE%E4%BA%BA%E6%95%B0%E3%82%92%E3%81%A7%E3%81%8D%E3%82%8B%E3%81%A0%E3%81%91%E5%9D%87%E7%AD%89%E5%8C%96%3A%0A%20%20%20%20%20%20%24%5Csum_%7Bi%20%5Cin%20T_1%7D%20x_%7Bi%20d%20s%7D%20%3D%20%5Csum_%7Bi%20%5Cin%20T_2%7D%20x_%7Bi%20d%20s%7D%24%20%24(%5Cforall%20d%2C%20s)%24.%20%E3%81%93%E3%82%8C%E3%81%AF%E5%88%B6%E7%B4%84%E3%81%A8%E3%81%84%E3%81%86%E3%82%88%E3%82%8A%E3%81%AF%E7%9B%AE%E7%9A%84%E9%96%A2%E6%95%B0%3F%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20OR-Tools%20Example%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%E5%8F%82%E8%80%83%3A%20https%3A%2F%2Fgithub.com%2Fgoogle%2For-tools%2Fblob%2Fstable%2Fexamples%2Fnotebook%2Fsat%2Fnurses_sat.ipynb%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cp_model)%3A%0A%20%20%20%20class%20NursesPartialSolutionPrinter(cp_model.CpSolverSolutionCallback)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Print%20intermediate%20solutions.%22%22%22%0A%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20shifts%2C%20num_nurses%2C%20num_days%2C%20num_shifts%2C%20limit)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20cp_model.CpSolverSolutionCallback.__init__(self)%0A%20%20%20%20%20%20%20%20%20%20%20%20self._shifts%20%3D%20shifts%0A%20%20%20%20%20%20%20%20%20%20%20%20self._num_nurses%20%3D%20num_nurses%0A%20%20%20%20%20%20%20%20%20%20%20%20self._num_days%20%3D%20num_days%0A%20%20%20%20%20%20%20%20%20%20%20%20self._num_shifts%20%3D%20num_shifts%0A%20%20%20%20%20%20%20%20%20%20%20%20self._solution_count%20%3D%200%0A%20%20%20%20%20%20%20%20%20%20%20%20self._solution_limit%20%3D%20limit%0A%0A%20%20%20%20%20%20%20%20def%20on_solution_callback(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self._solution_count%20%2B%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Solution%20%7Bself._solution_count%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20d%20in%20range(self._num_days)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Day%20%7Bd%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20n%20in%20range(self._num_nurses)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_working%20%3D%20False%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20s%20in%20range(self._num_shifts)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20self.value(self._shifts%5B(n%2C%20d%2C%20s)%5D)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20is_working%20%3D%20True%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20Nurse%20%7Bn%7D%20works%20shift%20%7Bs%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20not%20is_working%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20Nurse%20%7Bn%7D%20does%20not%20work%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20self._solution_count%20%3E%3D%20self._solution_limit%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22Stop%20search%20after%20%7Bself._solution_limit%7D%20solutions%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.stop_search()%0A%0A%20%20%20%20%20%20%20%20def%20solutionCount(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20self._solution_count%0A%20%20%20%20return%20(NursesPartialSolutionPrinter%2C)%0A%0A%0A%40app.cell%0Adef%20_(NursesPartialSolutionPrinter%2C%20cp_model)%3A%0A%20%20%20%20class%20Model%3A%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20num_nurses%3A%20int%2C%20num_shifts%3A%20int%2C%20num_days%3A%20int)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20all_nurses%20%3D%20range(num_nurses)%0A%20%20%20%20%20%20%20%20%20%20%20%20all_shifts%20%3D%20range(num_shifts)%0A%20%20%20%20%20%20%20%20%20%20%20%20all_days%20%3D%20range(num_days)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20model%20%3D%20cp_model.CpModel()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20shifts%5B(n%2C%20d%2C%20s)%5D%3A%20nurse%20'n'%20works%20shift%20's'%20on%20day%20'd'.%0A%20%20%20%20%20%20%20%20%20%20%20%20shifts%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(_n%2C%20_d%2C%20_s)%3A%20model.new_bool_var(f%22shift_n%7B_n%7D_d%7B_d%7D_s%7B_s%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_n%20in%20all_nurses%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_d%20in%20all_days%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_s%20in%20all_shifts%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Each%20shift%20is%20assigned%20to%20exactly%20one%20nurse%20in%20the%20schedule%20period.%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20_d%20in%20all_days%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_s%20in%20all_shifts%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add_exactly_one(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shifts%5B(_n%2C%20_d%2C%20_s)%5D%20for%20_n%20in%20all_nurses%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Each%20nurse%20works%20at%20most%20one%20shift%20per%20day.%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20_n%20in%20all_nurses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_d%20in%20all_days%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add_at_most_one(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shifts%5B(_n%2C%20_d%2C%20_s)%5D%20for%20_s%20in%20all_shifts%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Try%20to%20distribute%20the%20shifts%20evenly%2C%20so%20that%20each%20nurse%20works%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20min_shifts_per_nurse%20shifts.%20If%20this%20is%20not%20possible%2C%20because%20the%20total%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20number%20of%20shifts%20is%20not%20divisible%20by%20the%20number%20of%20nurses%2C%20some%20nurses%20will%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20be%20assigned%20one%20more%20shift.%0A%20%20%20%20%20%20%20%20%20%20%20%20min_shifts_per_nurse%20%3D%20(num_shifts%20*%20num_days)%20%2F%2F%20num_nurses%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20num_shifts%20*%20num_days%20%25%20num_nurses%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20max_shifts_per_nurse%20%3D%20min_shifts_per_nurse%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20max_shifts_per_nurse%20%3D%20min_shifts_per_nurse%20%2B%201%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20_n%20in%20all_nurses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shifts_worked%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_d%20in%20all_days%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_s%20in%20all_shifts%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shifts_worked.append(shifts%5B(_n%2C%20_d%2C%20_s)%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add(min_shifts_per_nurse%20%3C%3D%20sum(shifts_worked))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add(sum(shifts_worked)%20%3C%3D%20max_shifts_per_nurse)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E8%BF%BD%E5%8A%A0%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20shift%200%20%E3%82%92%E5%A4%9C%E5%8B%A4%E3%81%A8%E3%81%97%E3%81%A6%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20-%20%E5%A4%9C%E5%8B%A4%E3%81%AF%202%20%E9%80%A3%E7%B6%9A%E3%81%97%E3%81%AA%E3%81%91%E3%82%8C%E3%81%B0%E3%81%AA%E3%82%89%E3%81%AA%E3%81%84%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20-%20%E5%A4%9C%E5%8B%A4%E3%81%AF%203%20%E9%80%A3%E7%B6%9A%E3%81%97%E3%81%A6%E3%81%AF%E3%81%84%E3%81%91%E3%81%AA%E3%81%84%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E3%81%9F%E3%81%A0%E3%81%93%E3%82%8C%E3%81%A0%E3%81%A8%E5%A4%9C%E5%8B%A4%E3%81%8C%E5%81%8F%E3%81%A3%E3%81%A6%E3%81%97%E3%81%BE%E3%81%86%E3%81%AE%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%AE%E5%88%B6%E7%B4%84%E3%81%8C%E5%BF%85%E8%A6%81%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20_n%20in%20all_nurses%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add_implication(shifts%5B(_n%2C%200%2C%200)%5D%2C%20shifts%5B(_n%2C%201%2C%200)%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20_d%20in%20all_days%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20_d%20%3D%3D%200%20or%20_d%20%3D%3D%20num_days%20-%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add_implication(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shifts%5B(_n%2C%20_d%2C%200)%5D%2C%20shifts%5B(_n%2C%20_d%20%2B%201%2C%200)%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20).only_enforce_if(~shifts%5B(_n%2C%20_d%20-%201%2C%200)%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20model.add_bool_or(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B~shifts%5B(_n%2C%20_d%20%2B%20_t%2C%200)%5D%20for%20_t%20in%20%5B-1%2C%200%2C%201%5D%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.num_nurses%20%3D%20num_nurses%0A%20%20%20%20%20%20%20%20%20%20%20%20self.num_shifts%20%3D%20num_shifts%0A%20%20%20%20%20%20%20%20%20%20%20%20self.num_days%20%3D%20num_days%0A%20%20%20%20%20%20%20%20%20%20%20%20self.cpmodel%20%3D%20model%0A%20%20%20%20%20%20%20%20%20%20%20%20self.shifts%20%3D%20shifts%0A%0A%20%20%20%20%20%20%20%20def%20solve(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20solver%20%3D%20cp_model.CpSolver()%0A%20%20%20%20%20%20%20%20%20%20%20%20solver.parameters.linearization_level%20%3D%200%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Enumerate%20all%20solutions.%0A%20%20%20%20%20%20%20%20%20%20%20%20solver.parameters.enumerate_all_solutions%20%3D%20True%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20solution_limit%20%3D%205%0A%20%20%20%20%20%20%20%20%20%20%20%20solution_printer%20%3D%20NursesPartialSolutionPrinter(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.shifts%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.num_nurses%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.num_days%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.num_shifts%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20solution_limit%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20solver.solve(self.cpmodel%2C%20solution_printer)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20Statistics.%0A%20%20%20%20%20%20%20%20%20%20%20%20print(%22%5CnStatistics%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20-%20conflicts%20%20%20%20%20%20%3A%20%7Bsolver.num_conflicts%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20-%20branches%20%20%20%20%20%20%20%3A%20%7Bsolver.num_branches%7D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20-%20wall%20time%20%20%20%20%20%20%3A%20%7Bsolver.wall_time%7D%20s%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%20%20-%20solutions%20found%3A%20%7Bsolution_printer.solutionCount()%7D%22)%0A%20%20%20%20return%20(Model%2C)%0A%0A%0A%40app.cell%0Adef%20_(Model)%3A%0A%20%20%20%20model%20%3D%20Model(num_nurses%3D4%2C%20num_shifts%3D3%2C%20num_days%3D6)%0A%20%20%20%20model.solve()%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
f9699490428f424c42bb9177d06da95b915b1b9e2fcca25a19feca00f4f7384d