寻求OptaPlanner项目作业调度自定义输入格式指导
自定义OptaPlanner作业调度输入指南
一、先理清OptaPlanner输入的核心逻辑
OptaPlanner的输入本质是问题实体集合,核心分为三类:
- 问题事实(Problem Fact):固定不变的基础数据或约束条件,比如可用机器、工人、作业工艺路线、时间窗口等,这类数据不会被规划器修改
- 规划实体(Planning Entity):需要被调度/分配的对象,比如作业任务,它包含规划变量(Planning Variable)——也就是需要优化的属性,比如任务分配到哪台机器、任务开始时间
- 规划解决方案(Planning Solution):封装所有问题事实、规划实体的顶层容器,是规划器的输入和输出载体
二、构建自定义输入的具体步骤
1. 定义问题事实类
以机器资源为例,这类类不需要OptaPlanner注解,仅用于存储固定数据:
public class Machine { private Long id; private String name; private Integer capacity; // 机器最大承载量 // 无参构造器、getter/setter }
2. 定义规划实体类
以作业任务为例,标记需要优化的属性为规划变量:
@PlanningEntity public class Task { private Long id; private String taskName; private Integer duration; // 任务耗时(分钟) @PlanningVariable(valueRangeProviderRefs = {"machineRange"}) private Machine assignedMachine; // 待分配的机器 @PlanningVariable(valueRangeProviderRefs = {"timeRange"}) private LocalDateTime startTime; // 任务待确定的开始时间 // 无参构造器、getter/setter }
@PlanningEntity:标记该类是需要规划优化的实体@PlanningVariable:标记需要动态调整的属性,valueRangeProviderRefs关联该属性的可选值来源
3. 定义规划解决方案类
这是输入的顶层结构,整合所有问题事实和规划实体:
@PlanningSolution public class ScheduleSolution { // 问题事实:所有可用机器,同时作为assignedMachine的取值范围 @ProblemFactCollectionProperty @ValueRangeProvider(id = "machineRange") private List<Machine> machineList; // 规划实体:所有待调度任务 @PlanningEntityCollectionProperty private List<Task> taskList; // 问题事实:调度时间范围,作为startTime的取值范围 @ProblemFactProperty @ValueRangeProvider(id = "timeRange") private TimeRange timeRange; // 规划得分:输入时为null,规划器运行后填充评估结果 @PlanningScore private HardSoftScore score; // 无参构造器、getter/setter }
@PlanningSolution:标记该类是规划问题的解决方案载体@ProblemFactCollectionProperty/@ProblemFactProperty:标记问题事实数据@ValueRangeProvider:为规划变量提供可选值范围@PlanningEntityCollectionProperty:标记待优化的实体集合
三、JSON输入示例解析(对应上述模型)
以下是匹配上述类结构的JSON输入,可直接用于OptaPlanner的JSON反序列化:
{ "machineList": [ {"id": 1, "name": "MachineA", "capacity": 2}, {"id": 2, "name": "MachineB", "capacity": 1} ], "taskList": [ {"id": 101, "taskName": "Assembly", "duration": 180}, {"id": 102, "taskName": "Painting", "duration": 120} ], "timeRange": { "start": "2024-05-20T08:00:00", "end": "2024-05-20T18:00:00" }, "score": null }
machineList:固定机器资源,属于问题事实taskList:待调度任务,规划变量assignedMachine和startTime留空由规划器填充,也可设置初始值timeRange:定义任务开始时间的可选区间score:输入阶段无需赋值,规划器运行后会生成对应得分
四、关键注意事项
- 所有实体类必须包含无参构造器,否则JSON反序列化会失败
- 规划变量的取值范围必须通过
@ValueRangeProvider明确声明,要么来自问题事实集合,要么是数值/时间区间 - 如果存在任务依赖(如任务B必须在任务A完成后启动),需新增
TaskDependency这类问题事实类定义依赖关系,并在得分规则中实现约束逻辑
内容的提问来源于stack exchange,提问作者mmusab
相关产品推荐
相关产品推荐

