如何用OR-Tools实现任务优先级调度并最小化完工时间?
问题描述
车间未来两天需安排两项任务,仅配备1名操作员,每日只能完成1项任务。两项任务优先级不同,一项更紧急,另一项次之。需要确保在可行情况下优先安排更紧急的任务,同时实现该目标并最小化完工时间(Make Span)?
解决方案(OR-Tools SAT求解器实现)
以下是基于Google OR-Tools CP-SAT求解器的实现,已修正原代码的逻辑缺陷并将注释翻译为中文:
from ortools.sat.python import cp_model model = cp_model.CpModel() # 1. 数据定义 tasks = {0, 1} # 任务紧急程度映射:100代表更紧急,10次之 task_to_urgency_level = {0: 10, 1: 100} days = {0, 1} # 每日可用操作员数量:每天1名 day_to_operator_resource = {0: 1, 1: 1} # 2. 决策变量 max_date_index = max(days) # 存储每个任务分配到的日期索引 variables_task_day_index = { task: model.NewIntVar(0, max_date_index, f"task_{task}_day") for task in tasks } # 任务-日期分配矩阵(布尔变量:1表示任务分配到对应日期) variables_task_to_day_matrix = { (task, day): model.NewBoolVar(f"task_{task}_assigned_to_day_{day}") for task in tasks for day in days } # 3. 约束条件 # 每日任务数量不超过当日可用操作员数量 for day in days: model.Add( sum(variables_task_to_day_matrix[task, day] for task in tasks) <= day_to_operator_resource[day] ) # 每个任务只能分配到一个日期 for task in tasks: model.Add( sum(variables_task_to_day_matrix[task, day] for day in days) == 1 ) # 关联分配矩阵与任务日期索引变量 for task in tasks: for day in days: model.Add( variables_task_day_index[task] == day ).OnlyEnforceIf( variables_task_to_day_matrix[task, day] ) # 核心约束:确保更紧急任务的分配日期不晚于次紧急任务 urgent_task = [t for t in tasks if task_to_urgency_level[t] == 100][0] less_urgent_task = [t for t in tasks if task_to_urgency_level[t] == 10][0] model.Add(variables_task_day_index[urgent_task] <= variables_task_day_index[less_urgent_task]) # 4. 目标函数:最小化完工时间(所有任务完成日期的最大值) make_span = model.NewIntVar(0, 99999, "make_span") model.AddMaxEquality( make_span, [variables_task_day_index[task] for task in tasks] ) model.Minimize(make_span) # 5. 求解并输出结果 solver = cp_model.CpSolver() status = solver.Solve(model) if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE: print("任务分配结果:") for day in days: for task in tasks: if solver.Value(variables_task_to_day_matrix[task, day]): urgency_desc = "更紧急" if task_to_urgency_level[task] == 100 else "次之" print(f"任务{task}({urgency_desc})→ 第{day+1}天") print(f"最小完工时间:{solver.Value(make_span)+1}天") else: print("无可行解")
关键说明
- 修正原代码中
task_to_urgency_level的结构:原集合无法对应任务与紧急度的映射,改为字典后才能区分任务优先级。 - 添加紧急任务优先约束:通过强制更紧急任务的分配日期不晚于次紧急任务,确保优先安排逻辑生效。
- 最优解逻辑:在满足紧急优先的前提下,最小化完工时间的结果为:更紧急任务安排在第1天,次紧急任务安排在第2天,完工时间为2天,这是唯一可行且最优的方案。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

