You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 22:57:18