python 刀具调度问题的永远不可行解

f3temu5u  于 2023-05-16  发布在  Python
关注(0)|答案(1)|浏览(116)

假设一个预定义的枢纽列表,每个枢纽都有一个特定的驱动程序需求,一组驱动程序以及驱动程序和枢纽之间的关系。在我的例子中,驱动程序的数量远远高于集线器的数量,即。400 vs 45个枢纽,每天的需求量约为250名司机。我设置了一个约束,即每个司机也必须有一天休息。然而,我没有得到问题的解决方案,为了进一步促进解决方案,我甚至设置每个驱动程序可以在任何集线器(driver_hubs_relationships)工作,但仍然没有得到解决方案。有什么想法吗

def create_schedule(drivers,
                    hubs,
                    hubs_and_demand,
                    driver_hubs_relationships):
    drivers_list = copy.deepcopy(drivers)
    hubs_list = copy.deepcopy(hubs)
    hubs_list_and_demand = copy.deepcopy(hubs_and_demand)
    driver_hubs_list_relationships = copy.deepcopy(driver_hubs_relationships)

    model = cp_model.CpModel()

    # Define an extra "hub" that represents a day off
    hubs_list.append('OFF')
    for e in drivers_list:
        driver_hubs_list_relationships[e].append('OFF')

    # Create variables total size len(drivers)*(1+len(hubs))*len(days)
    schedule = {}
    for e in drivers_list:
        for d in days:
            for r in hubs_list:
                schedule[(e, d, r)] = model.NewBoolVar(f'schedule_{e}_{d}_{r}')

    # Define a variable for each day representing the number of drivers having that day off
    off_days = {d: model.NewIntVar(0, len(drivers_list), f'off_{d}') for d in days}

    # Add constraints to link the off_days variable with the schedule variable
    for d in days:
        model.Add(off_days[d] == sum(schedule[(e, d, 'OFF')] for e in drivers_list))

    # Add a constraint to distribute the off days evenly across the week
    average_off_days = len(drivers_list) // len(days)
    for d in days:
        model.Add(off_days[d] >= average_off_days)

    # Each driver must have one day off per week
    for e in drivers_list:
        model.Add(sum(schedule[(e, d, 'OFF')] for d in days) == 1)

    # Each driver works at most one day at a specific hub
    for e in drivers_list:
        for d in days:
            model.Add(sum(schedule[(e, d, r)] for r in hubs_list) == 1)

    # Create variables for the number of drivers needed at each hub on each day
    drivers_needed = {}
    for d in days:
        for r in hubs_list:
            if r != 'OFF':
                hub_demand = hubs_list_and_demand.loc[hubs_list_and_demand['hub'] == r, 'drivers_needed']
                if len(hub_demand) > 0:
                    drivers_needed_at_hub = int(hub_demand.values[0])
                else:
                    drivers_needed_at_hub = 0  # or some other default value
                drivers_needed[(d, r)] = model.NewIntVar(drivers_needed_at_hub,
                                                         int(hubs_list_and_demand.max().values[1]),
                                                         f'drivers_needed_{d}_{r}')

    # Each hub needs to have the required number of drivers each day
    for d in days:
        for r in hubs_list:
            if r != 'OFF':
                model.Add(10 * sum(schedule[(e, d, r)] for e in drivers_list) >=
                          9 * drivers_needed[(d, r)])

    # Assign each driver to their specific hub
    for e in drivers_list:
        for r in hubs_list:
            if r not in driver_hubs_list_relationships[e]:
                for d in days:
                    model.Add(schedule[(e, d, r)] == 0)

    # Solve and print schedule
    solver = cp_model.CpSolver()
    solver.parameters.max_time_in_seconds = 500.0
    solver.parameters.log_search_progress = True
    status = solver.Solve(model)
    print(f"status code {status}")
    if status == cp_model.OPTIMAL:
        solution = {}
        for e in drivers_list:
            solution[e] = {}
            for d in days:
                for r in hubs_list:
                    if solver.Value(schedule[(e, d, r)]) == 1:
                        print(f"{e} works at {r} on {d}")
                        solution[e][d] = r

        return solution
    else:
        return None
k97glaaz

k97glaaz1#

我认为你对你的休息日有矛盾/问题:

# Add a constraint to distribute the off days evenly across the week
average_off_days = len(drivers_list) // len(days)
for d in days:
    model.Add(off_days[d] >= average_off_days)

# Each driver must have one day off per week
for e in drivers_list:
    model.Add(sum(schedule[(e, d, 'OFF')] for d in days) == 1)

如果你有很多多余的司机,他们可能会有多天的休息,但你只允许他们1天休息。尝试将第二个约束设置为GTE >=
此外,从您提供的内容中,还不清楚为什么要按day索引days_off约束?如果你的模型是以满足需求为结构的,那么就不需要强制每天的休息天数是固定的。如果每天的“休息日司机”都是平等的,那就太奇怪了,这基本上就是你所强迫的。

添加:

另外,不清楚为什么要为drivers_needed创建一个变量。这是一个已知的(或至少是一个可计算的)数据值。这不是未知的,是吗?我没有遵循这组语句中的所有逻辑,但似乎你应该能够用一点数学计算出按天/按“枢纽”的需求,并将其作为模型的参数,而不是变量。

相关问题