Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 平衡每日覆盖的限制_Python_Or Tools_Cp Sat Solver - Fatal编程技术网

Python 平衡每日覆盖的限制

Python 平衡每日覆盖的限制,python,or-tools,cp-sat-solver,Python,Or Tools,Cp Sat Solver,以下是我的问题公式的简化版本: from ortools.sat.python import cp_model def solve_shift_scheduling(): num_employees = 6 num_weeks = 4 shifts = ['.', 'M'] fixed_assignments = [ (0, 1, 0), (0, 1, 2), (0, 1, 5), (1, 0,

以下是我的问题公式的简化版本:

from ortools.sat.python import cp_model

def solve_shift_scheduling():
    num_employees = 6
    num_weeks = 4
    shifts = ['.', 'M']

    fixed_assignments = [
        (0, 1, 0),
        (0, 1, 2),
        (0, 1, 5),
        (1, 0, 0),
        (1, 1, 1),
        (1, 1, 6),
        (2, 1, 0),
        (2, 1, 2),
        (2, 1, 5),
        (2, 1, 6),
        (5, 1, 1),
        (5, 1, 5)]
        
    requests = [
        (3, 1, 3, -2),
        (3, 1, 4, -2), 
        (4, 1, 2, -2),
        (4, 1, 3, -2),
        (4, 1, 4, -2)]

    weekly_cover_demands = [
        (4,),  # Monday
        (4,),  # Tuesday
        (4,),  # Wednesday
        (4,),  # Thursday
        (4,),  # Friday
        (4,),  # Saturday
        (4,),  # Sunday
    ]
    
    employee_max_shifts = [
        (1,3), # employee 0
        (1,3), # employee 1
        (1,4), # employee 2
        (1,2), # employee 3
        (1,3), # employee 4
        (1,2), # employee 5
    ]

    num_days = num_weeks * 7
    num_shifts = len(shifts)

    model = cp_model.CpModel()

    work = {}
    for e in range(num_employees):
        for s in range(num_shifts):
            for d in range(num_days):
                work[e, s, d] = model.NewBoolVar('work%i_%i_%i' % (e, s, d))

    # Linear terms of the objective in a minimization context.
    obj_int_vars = []
    obj_int_coeffs = []
    obj_bool_vars = []
    obj_bool_coeffs = []

    # Exactly one shift per day.
    for e in range(num_employees):
        for d in range(num_days):
            model.Add(sum(work[e, s, d] for s in range(num_shifts)) == 1)

    # Fixed assignments.
    for e, s, d in fixed_assignments:
        model.Add(work[e, s, d] == 1)

    # Employee requests
    for e, s, d, w in requests:
        obj_bool_vars.append(work[e, s, d])
        obj_bool_coeffs.append(w)
        
    # Employee shifts constraint
    for e in range(num_employees):
         for w in range(num_weeks):
            s, max_shifts = employee_max_shifts[e]
            works = [work[e, s, d + w * 7] for d in range(7)]
            total_shifts = model.NewIntVar(0, max_shifts, '')
            model.Add(total_shifts==sum(works))
                
    # Cover constraints
    for s in range(1, num_shifts):
        for w in range(num_weeks):
            for d in range(7):
                works = [work[e, s, w * 7 + d] for e in range(num_employees)]
                demand = weekly_cover_demands[d][s - 1]
                worked = model.NewIntVar(0, demand, '')
                model.Add(worked == sum(works))
                name = 'under_demand: (shift={}, week={}, day={})'.format(s, w, d)
                under = model.NewIntVar(0, demand, name)
                model.Add(under == demand - worked)
                obj_int_vars.append(under)
                obj_int_coeffs.append(20)
            
    # Objective
    model.Minimize(
        sum(obj_bool_vars[i] * obj_bool_coeffs[i]
            for i in range(len(obj_bool_vars))) +
        sum(obj_int_vars[i] * obj_int_coeffs[i]
            for i in range(len(obj_int_vars))))

    # Solve the model.
    solver = cp_model.CpSolver()
    solver.parameters.num_search_workers = 8
    solver.parameters.max_time_in_seconds = 600
    solution_printer = cp_model.ObjectiveSolutionPrinter()
    status = solver.SolveWithSolutionCallback(model, solution_printer)
    
    # Print solution.
    if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
        print()
        header = '          '
        for w in range(num_weeks):
            header += 'M T W T F S S '
        print(header)
        for e in range(num_employees):
            schedule = ''
            for d in range(num_days):
                for s in range(num_shifts):
                    if solver.BooleanValue(work[e, s, d]):
                        schedule += shifts[s] + ' '
            print('worker %i: %s' % (e, schedule))
此外,我还想添加一个条件,尝试平衡每日覆盖范围:

    # Balance Coverage 
    for s in range(1, num_shifts):
        for w in range(num_weeks):
            each_days_gap = []
            daily_demands = []
            for d in range(7):
                demand = weekly_cover_demands[d][s - 1]
                daily_demands.append(demand)
                works = [work[e, s, w*7+d] for e in range(num_employees)]
                demand_gap = model.NewIntVar(0, demand, '')
                model.Add((demand - sum(works)) == demand_gap)
                each_days_gap.append(demand_gap)
            min_demand_gap = model.NewIntVar(0, max(daily_demands), '')
            max_demand_gap = model.NewIntVar(0, max(daily_demands), '')
            model.AddMinEquality(min_demand_gap, each_days_gap)
            model.AddMaxEquality(max_demand_gap, each_days_gap)
            name = 'target_gap: (shift={}, week={})'.format(s,w)
            delta = model.NewIntVar(0, max(daily_demands), name)
            model.Add(delta == max_demand_gap-min_demand_gap)
            obj_int_vars.append(delta)
            obj_int_coeffs.append(10)

添加此规则会导致运行时间增加+20倍,这意味着添加额外的约束后,问题开始需要10分钟以上才能解决。是否有更有效的方法来实现上述规则?

不适用于示例中包含的模型。你用的是更大的模型吗?@LaurentPerron,是的,我的模型更大。有更多的员工(~50),更多的轮班类型(~9),员工等级制度,加班最小化,以及一些关于轮班频率/休息的规则。一般来说,在尝试平衡覆盖范围时,您是否认为此最小/最大增量最小化策略有用,还是倾向于采用不同的方法?感谢您的回复和您所有令人难以置信的工作或工具!