简体   繁体   English

时间表不会显示

[英]Schedule won't show up

I've copied a code example that works fine by itself, and does work in my version as well.我复制了一个代码示例,它本身可以正常工作,并且在我的版本中也可以工作。 The problem is after asking the user the number of employees, shifts, and days being scheduled, the program won't display the results of the solver.问题是在询问用户员工人数、班次和计划天数后,程序不会显示求解器的结果。 It will do this for the example code alone, but not with the code I have written to control it.它将仅针对示例代码执行此操作,但不会针对我为控制它而编写的代码执行此操作。 If anyone can take a look at this to see why, it would be greatly appreciated.如果有人可以看看这个,看看为什么,将不胜感激。

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()

Past a certain point, it's better to try a cleaner approach than to pinpoint where precisely the current one is going wrong.过了某个时间点,最好尝试一种更简洁的方法,而不是精确定位当前错误的位置。 Here's a stab at a better way to structure what you're doing, and it appears to work correctly.这是一种更好的方式来构建你正在做的事情,它似乎可以正常工作。

First, the code copied from the example , with "nurses" replaced by "employees" and the static assignments changed to user input, as you've done.首先,从示例中复制的代码,将“nurses”替换为“employees”,并且 static 分配更改为用户输入,正如您所做的那样。 I've also renamed main to schedule_employees .我还将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)

This, more or less, is all you need to add/change.这或多或少是您需要添加/更改的全部内容。 The top level entry point -- basically, the stuff you want to happen first when you execute your script -- goes inside the __name__ == '__main__' check, just like the example did it.顶级入口点——基本上,当你执行你的脚本时你想首先发生的事情——进入__name__ == '__main__'检查,就像示例所做的那样。 The difference, of course, is that we're performing a couple of checks prior to calling what used to simply be the main method.当然,不同之处在于我们在调用过去只是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()

If you add to this program and these checks become more complex, you might consider bundling them off into your own new main method, or even making a separate get_role method for example, but for now this is short and simple enough that it's fine here.如果您添加到这个程序并且这些检查变得更加复杂,您可能会考虑将它们捆绑到您自己的新main方法中,或者甚至制作一个单独的get_role方法,但现在这很简短,在这里很好。

The basic rule is: define your classes and functions and such first, at the top level, and then use whatever control flow logic you want in order to decide what to call, how, and when.基本规则是:首先在顶层定义您的类和函数等,然后使用您想要的任何控制流逻辑来决定调用什么、如何调用以及何时调用。 There are reasons you might eventually want to define classes inside conditionals and/or functions, but it's pretty unusual and for complex situations.您最终可能希望在条件和/或函数中定义类,但这是非常不寻常的,并且适用于复杂的情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM