时间表不会显示
Schedule won't show up
我复制了一个 code example,它本身运行良好,在我的版本中也能运行。问题是在询问用户员工人数、班次和计划天数后,程序不会显示求解器的结果。它将仅针对示例代码执行此操作,但不会使用我编写的用于控制它的代码。如果有人可以看一下这个以了解原因,将不胜感激。
from ortools.sat.python import cp_model
def sup_functions(): # supervisor functions
sup_task = input('I want to: ')
# scheduling employees
if sup_task == 'schedule employees':
class EmpsPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
def __init__(self, shifts, num_emps, num_days, num_shifts, sols):
cp_model.CpSolverSolutionCallback.__init__(self)
self._shifts = shifts
self._num_emps = num_emps
self._num_days = num_days
self._num_shifts = num_shifts
self._solutions = set(sols)
self._solution_count = 1
def on_solution_callback(self):
if self._solution_count in self._solutions:
print('Solution %i' % self._solution_count)
for d in range(self._num_days):
print('Day %i' % d)
for n in range(self._num_emps):
is_working = False
for s in range(self._num_shifts):
if self.Value(self._shifts[(n, d, s)]):
is_working = True
print(' Employee %i works shift %i' % (n, s))
if not is_working:
print(' Employee {} does not work'.format(n))
print()
self._solution_count += 1
def solution_count(self):
return self._solution_count
def main():
# Data.
num_emps = int(input("How many employees are you scheduling? "))
num_days = int(input("How many days are you scheduling for? "))
num_shifts = int(input(f"How many shifts are you scheduling for each employees for {num_days} days? "))
all_emps = range(num_emps)
all_shifts = range(num_shifts)
all_days = range(num_days)
# Creates the model.
model = cp_model.CpModel()
# Creates shift variables.
# shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
shifts = {}
for n in all_emps:
for d in all_days:
for s in all_shifts:
shifts[(n, d,
s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))
# Each shift is assigned to exactly one employee in the schedule period.
for d in all_days:
for s in all_shifts:
model.Add(sum(shifts[(n, d, s)] for n in all_emps) == 1)
# Each emmployee works at most one shift per day.
for n in all_emps:
for d in all_days:
model.Add(sum(shifts[(n, d, s)] for s in all_shifts) <= 1)
# Try to distribute the shifts evenly, so that each employee works
# min_shifts_per_emp shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of employees, some employees will
# be assigned one more shift.
min_shifts_per_emp = (num_shifts * num_days) // num_emps
if num_shifts * num_days % num_emps == 0:
max_shifts_per_emp = min_shifts_per_emp
else:
max_shifts_per_emp = min_shifts_per_emp + 1
for n in all_emps:
num_shifts_worked = 0
for d in all_days:
for s in all_shifts:
num_shifts_worked += shifts[(n, d, s)]
model.Add(min_shifts_per_emp <= num_shifts_worked)
model.Add(num_shifts_worked <= max_shifts_per_emp)
# Creates the solver and solve.
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Display the first five solutions.
a_few_solutions = range(5)
solution_printer = EmpsPartialSolutionPrinter(shifts, num_emps,
num_days, num_shifts,
a_few_solutions)
solver.SearchForAllSolutions(model, solution_printer)
if __name__ == '__main__':
main()
# lets program know which functions to call
def emporsup():
emp_or_sup = input('Are you an employee or supervisor? ') # determines if user is an employee or the owner
if emp_or_sup == "supervisor":
sup_functions()
#elif emp_or_sup == "employee":
#emp_functions()
else:
print("not a valid response")
emporsup()
emporsup()
过了某个点,最好尝试一种更简洁的方法,而不是查明当前方法的确切错误位置。这是一种更好的方式来构建你正在做的事情,它似乎工作正常。
首先,从 example 复制的代码,将“护士”替换为“员工”,并将静态分配更改为用户输入,正如您所做的那样。我还将 main
重命名为 schedule_employees
。
from ortools.sat.python import cp_model
class EmpsPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""
def __init__(self, shifts, num_employees, num_days, num_shifts, sols):
cp_model.CpSolverSolutionCallback.__init__(self)
self._shifts = shifts
self._num_employees = num_employees
self._num_days = num_days
self._num_shifts = num_shifts
self._solutions = set(sols)
self._solution_count = 0
def on_solution_callback(self):
if self._solution_count in self._solutions:
print('Solution %i' % self._solution_count)
for d in range(self._num_days):
print('Day %i' % d)
for n in range(self._num_employees):
is_working = False
for s in range(self._num_shifts):
if self.Value(self._shifts[(n, d, s)]):
is_working = True
print(' Nurse %i works shift %i' % (n, s))
if not is_working:
print(' Nurse {} does not work'.format(n))
print()
self._solution_count += 1
def solution_count(self):
return self._solution_count
def schedule_employees():
# Data.
num_employees = int(input("How many employees are you scheduling? "))
num_days = int(input("How many days are you scheduling for? "))
num_shifts = int(input("How many shifts are you scheduling for each "
f"employees for {num_days} days? "))
all_employees = range(num_employees)
all_shifts = range(num_shifts)
all_days = range(num_days)
# Creates the model.
model = cp_model.CpModel()
# Creates shift variables.
# shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
shifts = {}
for n in all_employees:
for d in all_days:
for s in all_shifts:
shifts[(n, d,
s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))
# Each shift is assigned to exactly one nurse in the schedule period.
for d in all_days:
for s in all_shifts:
model.Add(sum(shifts[(n, d, s)] for n in all_employees) == 1)
# Each nurse works at most one shift per day.
for n in all_employees:
for d in all_days:
model.Add(sum(shifts[(n, d, s)] for s in all_shifts) <= 1)
# Try to distribute the shifts evenly, so that each nurse works
# min_shifts_per_nurse shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of employees, some employees will
# be assigned one more shift.
min_shifts_per_nurse = (num_shifts * num_days) // num_employees
if num_shifts * num_days % num_employees == 0:
max_shifts_per_nurse = min_shifts_per_nurse
else:
max_shifts_per_nurse = min_shifts_per_nurse + 1
for n in all_employees:
num_shifts_worked = 0
for d in all_days:
for s in all_shifts:
num_shifts_worked += shifts[(n, d, s)]
model.Add(min_shifts_per_nurse <= num_shifts_worked)
model.Add(num_shifts_worked <= max_shifts_per_nurse)
# Creates the solver and solve.
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Display the first five solutions.
a_few_solutions = range(5)
solution_printer = EmpsPartialSolutionPrinter(shifts, num_employees,
num_days, num_shifts,
a_few_solutions)
solver.SearchForAllSolutions(model, solution_printer)
这或多或少就是您所需要的 add/change。顶级入口点——基本上,您希望在执行脚本时首先发生的事情——进入 __name__ == '__main__'
检查,就像示例所做的那样。当然,不同之处在于我们在调用以前只是 main
方法之前执行了一些检查。
if __name__ == '__main__':
valid_roles = ['supervisor', 'employee']
role = input('Are you an employee or supervisor? ')
while role not in valid_roles:
print('not a valid response')
role = input('Are you an employee or supervisor? ')
task = input('I want to: ')
if role == 'supervisor' and task == 'schedule employees':
schedule_employees()
如果你添加到这个程序并且这些检查变得更加复杂,你可以考虑将它们捆绑到你自己的新 main
方法中,或者甚至制作一个单独的 get_role
方法,但是现在这很简短,在这里很好。
基本规则是:首先在顶层定义您的 类 和函数等,然后 然后 使用您想要的任何控制流逻辑,以便决定呼叫什么、如何呼叫以及何时呼叫。您可能最终想要在条件 and/or 函数中定义 类 是有原因的,但这很不寻常并且适用于复杂的情况。
我复制了一个 code example,它本身运行良好,在我的版本中也能运行。问题是在询问用户员工人数、班次和计划天数后,程序不会显示求解器的结果。它将仅针对示例代码执行此操作,但不会使用我编写的用于控制它的代码。如果有人可以看一下这个以了解原因,将不胜感激。
from ortools.sat.python import cp_model
def sup_functions(): # supervisor functions
sup_task = input('I want to: ')
# scheduling employees
if sup_task == 'schedule employees':
class EmpsPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
def __init__(self, shifts, num_emps, num_days, num_shifts, sols):
cp_model.CpSolverSolutionCallback.__init__(self)
self._shifts = shifts
self._num_emps = num_emps
self._num_days = num_days
self._num_shifts = num_shifts
self._solutions = set(sols)
self._solution_count = 1
def on_solution_callback(self):
if self._solution_count in self._solutions:
print('Solution %i' % self._solution_count)
for d in range(self._num_days):
print('Day %i' % d)
for n in range(self._num_emps):
is_working = False
for s in range(self._num_shifts):
if self.Value(self._shifts[(n, d, s)]):
is_working = True
print(' Employee %i works shift %i' % (n, s))
if not is_working:
print(' Employee {} does not work'.format(n))
print()
self._solution_count += 1
def solution_count(self):
return self._solution_count
def main():
# Data.
num_emps = int(input("How many employees are you scheduling? "))
num_days = int(input("How many days are you scheduling for? "))
num_shifts = int(input(f"How many shifts are you scheduling for each employees for {num_days} days? "))
all_emps = range(num_emps)
all_shifts = range(num_shifts)
all_days = range(num_days)
# Creates the model.
model = cp_model.CpModel()
# Creates shift variables.
# shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
shifts = {}
for n in all_emps:
for d in all_days:
for s in all_shifts:
shifts[(n, d,
s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))
# Each shift is assigned to exactly one employee in the schedule period.
for d in all_days:
for s in all_shifts:
model.Add(sum(shifts[(n, d, s)] for n in all_emps) == 1)
# Each emmployee works at most one shift per day.
for n in all_emps:
for d in all_days:
model.Add(sum(shifts[(n, d, s)] for s in all_shifts) <= 1)
# Try to distribute the shifts evenly, so that each employee works
# min_shifts_per_emp shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of employees, some employees will
# be assigned one more shift.
min_shifts_per_emp = (num_shifts * num_days) // num_emps
if num_shifts * num_days % num_emps == 0:
max_shifts_per_emp = min_shifts_per_emp
else:
max_shifts_per_emp = min_shifts_per_emp + 1
for n in all_emps:
num_shifts_worked = 0
for d in all_days:
for s in all_shifts:
num_shifts_worked += shifts[(n, d, s)]
model.Add(min_shifts_per_emp <= num_shifts_worked)
model.Add(num_shifts_worked <= max_shifts_per_emp)
# Creates the solver and solve.
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Display the first five solutions.
a_few_solutions = range(5)
solution_printer = EmpsPartialSolutionPrinter(shifts, num_emps,
num_days, num_shifts,
a_few_solutions)
solver.SearchForAllSolutions(model, solution_printer)
if __name__ == '__main__':
main()
# lets program know which functions to call
def emporsup():
emp_or_sup = input('Are you an employee or supervisor? ') # determines if user is an employee or the owner
if emp_or_sup == "supervisor":
sup_functions()
#elif emp_or_sup == "employee":
#emp_functions()
else:
print("not a valid response")
emporsup()
emporsup()
过了某个点,最好尝试一种更简洁的方法,而不是查明当前方法的确切错误位置。这是一种更好的方式来构建你正在做的事情,它似乎工作正常。
首先,从 example 复制的代码,将“护士”替换为“员工”,并将静态分配更改为用户输入,正如您所做的那样。我还将 main
重命名为 schedule_employees
。
from ortools.sat.python import cp_model
class EmpsPartialSolutionPrinter(cp_model.CpSolverSolutionCallback):
"""Print intermediate solutions."""
def __init__(self, shifts, num_employees, num_days, num_shifts, sols):
cp_model.CpSolverSolutionCallback.__init__(self)
self._shifts = shifts
self._num_employees = num_employees
self._num_days = num_days
self._num_shifts = num_shifts
self._solutions = set(sols)
self._solution_count = 0
def on_solution_callback(self):
if self._solution_count in self._solutions:
print('Solution %i' % self._solution_count)
for d in range(self._num_days):
print('Day %i' % d)
for n in range(self._num_employees):
is_working = False
for s in range(self._num_shifts):
if self.Value(self._shifts[(n, d, s)]):
is_working = True
print(' Nurse %i works shift %i' % (n, s))
if not is_working:
print(' Nurse {} does not work'.format(n))
print()
self._solution_count += 1
def solution_count(self):
return self._solution_count
def schedule_employees():
# Data.
num_employees = int(input("How many employees are you scheduling? "))
num_days = int(input("How many days are you scheduling for? "))
num_shifts = int(input("How many shifts are you scheduling for each "
f"employees for {num_days} days? "))
all_employees = range(num_employees)
all_shifts = range(num_shifts)
all_days = range(num_days)
# Creates the model.
model = cp_model.CpModel()
# Creates shift variables.
# shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
shifts = {}
for n in all_employees:
for d in all_days:
for s in all_shifts:
shifts[(n, d,
s)] = model.NewBoolVar('shift_n%id%is%i' % (n, d, s))
# Each shift is assigned to exactly one nurse in the schedule period.
for d in all_days:
for s in all_shifts:
model.Add(sum(shifts[(n, d, s)] for n in all_employees) == 1)
# Each nurse works at most one shift per day.
for n in all_employees:
for d in all_days:
model.Add(sum(shifts[(n, d, s)] for s in all_shifts) <= 1)
# Try to distribute the shifts evenly, so that each nurse works
# min_shifts_per_nurse shifts. If this is not possible, because the total
# number of shifts is not divisible by the number of employees, some employees will
# be assigned one more shift.
min_shifts_per_nurse = (num_shifts * num_days) // num_employees
if num_shifts * num_days % num_employees == 0:
max_shifts_per_nurse = min_shifts_per_nurse
else:
max_shifts_per_nurse = min_shifts_per_nurse + 1
for n in all_employees:
num_shifts_worked = 0
for d in all_days:
for s in all_shifts:
num_shifts_worked += shifts[(n, d, s)]
model.Add(min_shifts_per_nurse <= num_shifts_worked)
model.Add(num_shifts_worked <= max_shifts_per_nurse)
# Creates the solver and solve.
solver = cp_model.CpSolver()
solver.parameters.linearization_level = 0
# Display the first five solutions.
a_few_solutions = range(5)
solution_printer = EmpsPartialSolutionPrinter(shifts, num_employees,
num_days, num_shifts,
a_few_solutions)
solver.SearchForAllSolutions(model, solution_printer)
这或多或少就是您所需要的 add/change。顶级入口点——基本上,您希望在执行脚本时首先发生的事情——进入 __name__ == '__main__'
检查,就像示例所做的那样。当然,不同之处在于我们在调用以前只是 main
方法之前执行了一些检查。
if __name__ == '__main__':
valid_roles = ['supervisor', 'employee']
role = input('Are you an employee or supervisor? ')
while role not in valid_roles:
print('not a valid response')
role = input('Are you an employee or supervisor? ')
task = input('I want to: ')
if role == 'supervisor' and task == 'schedule employees':
schedule_employees()
如果你添加到这个程序并且这些检查变得更加复杂,你可以考虑将它们捆绑到你自己的新 main
方法中,或者甚至制作一个单独的 get_role
方法,但是现在这很简短,在这里很好。
基本规则是:首先在顶层定义您的 类 和函数等,然后 然后 使用您想要的任何控制流逻辑,以便决定呼叫什么、如何呼叫以及何时呼叫。您可能最终想要在条件 and/or 函数中定义 类 是有原因的,但这很不寻常并且适用于复杂的情况。