如何编写一个约束,使得 1 个任务仅由 1 个工作人员完成 | Google OR-工具|日程安排问题

问题描述 投票:0回答:1

我正在使用 google OR-Tools 来解决调度问题。

该设置有 6 个班次、3 个任务和 3 名工人。 (数字将来可能会发生变化。)

工人被命名为A、B、C。

数量是指完成该任务需要多少班次。(每个任务预定义。)

如果可能的话,我想编写一个约束,使得任务 1 仅由 1 个工作人员完成。并且 1 名工人不能在同一班次/时间内执行多项任务。

如何使用 google OR-Tools 编写这样的约束?


示例代码

import pandas as pd
from ortools.sat.python import cp_model

""" Inputs """
num_workers = 3
num_shifts = 6
task_info = {
    "task-1": 3,
    "task-2": 3,
    "task-3": 2,
}

""" Processing """
num_tasks = len(task_info)
quantities = list(task_info.values())

model = cp_model.CpModel()

shifts = {}
maximize_this = 0
for t in range(num_tasks):
    for s in range(num_shifts):
        for w in range(num_workers):
            shifts[(t, s, w)] = model.NewBoolVar(f't{t} s{s} w{w}')
            maximize_this += shifts[(t, s, w)]


for s in range(num_shifts):
    for w in range(num_workers):
        # Constraint: 1 worker in 1 shift can do at most 1 task of 1 quantity
        model.Add(sum(shifts[(t, s, w)] for t in range(num_tasks)) <= 1)
    for t in range(num_tasks):
        # Constraint: 1 task is done by at most 1 worker in 1 shift
        model.Add(sum(shifts[(t, s, w)] for w in range(num_workers)) <= 1)

# Constraint: 1 task of n quantity is done by 1 worker in n shifts
for t in range(num_tasks):
    model.Add(sum(sum(shifts[(t, s, w)] for s in range(num_shifts))
              for w in range(num_workers)) <= quantities[t])

# Constraint: 1 worker for 1 task if possible
# Need Suggestions

# To complete as many tasks as possible
model.Maximize(maximize_this)

solver = cp_model.CpSolver()
status = solver.Solve(model)

""" Output """
if status == cp_model.OPTIMAL:
    alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    data = []
    for t in range(num_tasks):
        data_i = []
        for s in range(num_shifts):
            s_val = ""
            for w in range(num_workers):
                if solver.Value(shifts[(t, s, w)]) == 1:
                    s_val = f'{alphabets[w]}'
            data_i.append(s_val)
        data.append(data_i)

    data = pd.DataFrame(
        data,
        index=list(task_info.keys()),
        columns=[f'shift-{s}' for s in range(num_shifts)])
    data["quantity"] = quantities

    print(data)
else:
    print("No solution found")

电流输出

shift-1 shift-2 shift-3 shift-4 shift-5 shift-6 数量
任务1 B B B 3
任务2 C A A 3
任务3 A B 2

预期输出示例

我想要的一个可能的输出如下表所示。

shift-1 shift-2 shift-3 shift-4 shift-5 shift-6 数量
任务1 A A A 3
任务2 B B B 3
任务3 C C 2

编辑1

检查cph的答案后,我尝试写这个但无法完成......

for t in range(num_tasks):
    for w in range(num_workers):
        m_this = model.NewIntVar(0, num_shifts, "")
        # model.Add(m_this == sum(shifts[(t, s, w)] for s in range(num_shifts)))
        model.AddMaxEquality(m_this, [shifts[(t, s, w)] for s in range(num_shifts)])

        m_others = model.NewIntVar(0, num_shifts, "")
        # model.Add(m_others == sum(sum(shifts[(t, s, w1)] for s in range(num_shifts)) for w1 in range(num_workers) if w != w1))
        model.AddMaxEquality(m_others, [shifts[(t, s, w1)] for s in range(num_shifts) for w1 in range(num_workers) if w != w1])

        model.AddImplication(m_this, m_others.Not())
python constraints scheduled-tasks or-tools cp-sat
1个回答
0
投票

一个问题:为什么你的约束“n 数量的 1 项任务由 1 名工人在 n 班次中完成”使用 <= quantities[t] instead of == quantities[t]? Don't you want the number of shifts for the task to exactly equal the quantity? I guess it's because you are maximizing the number of task steps done during the shifts instead of minimizing the number of shifts required to finish all the defined tasks.

您正在寻找的约束可以用这样的元代码来表达:

For each worker w
    For each task t
        Let m_this = maximum value of all the shifts[(t, s, w)] for s = 1 to num_shifts
        Let m_others = maximum value of all the shifts[(t, s, w1)] for s = 1 to num_shifts and w1 = 1 to num_workers, except where w1 = w
        Add the constraint (m_this implies not m_others)

我对 Python 完全是门外汉,但我相信你可以通过

model.AddMaxEquality(m_this, <list of the BoolVar's>)
获得最大的收益。

可以使用

model.AddImplication(m_this, m_others.Not())
""

添加含义
© www.soinside.com 2019 - 2024. All rights reserved.