OptaPlanner多规划实体组合报错及调度需求实现咨询
OptaPlanner调度问题错误排查与需求实现指导
错误根源分析
你遇到的错误是因为普通@PlanningVariable只能绑定单个候选值,但你定义的employeeList是List<Employee>类型,而@ValueRangeProvider提供的是单个Employee实例的集合,类型不匹配导致无法赋值。
错误修复方案
OptaPlanner 8.2及以上版本支持集合类型的规划变量,使用@PlanningListVariable替代@PlanningVariable即可解决类型匹配问题,它会自动从候选集中生成合法的子集作为变量值。
代码修正示例
1. Vehicle实体类调整
@PlanningEntity public class Vehicle { // 车辆容量属性 private Integer capacity; // 替换@PlanningVariable为@PlanningListVariable,指定值范围提供者ID @PlanningListVariable(valueRangeProviderRefs = "employeeRange") private List<Employee> employeeList; // 省略getter、setter及其他字段 }
2. Solution类保持原ValueRangeProvider(无需修改)
@PlanningSolution public class ScheduleSolution { private List<Employee> employees; private List<Vehicle> vehicles; private List<Job> jobs; // 评分器等其他字段 // 提供单个Employee的候选集 @ValueRangeProvider(id = "employeeRange") public List<Employee> getEmployees() { return employees; } // 省略getter、setter及其他方法 }
核心需求实现
1. 车辆搭载员工数不超容量
通过约束规则限制employeeList的大小不超过车辆容量:
@Constraint public Constraint vehicleEmployeeCapacity(ConstraintFactory constraintFactory) { return constraintFactory.from(Vehicle.class) .filter(vehicle -> vehicle.getEmployeeList().size() > vehicle.getCapacity()) .penalize("Vehicle over capacity", HardSoftScore.ONE_HARD, vehicle -> vehicle.getEmployeeList().size() - vehicle.getCapacity()); }
2. 员工任务数控制在10-30之间
首先给Employee添加派生属性assignedJobs(从Job的分配结果聚合得到),再编写约束:
// Employee类中添加派生属性 public List<Job> getAssignedJobs() { // 从所有Job中筛选分配给当前员工的任务 return jobs.stream() .filter(job -> this.equals(job.getAssignedEmployee())) .collect(Collectors.toList()); } // 约束规则 @Constraint public Constraint employeeJobCountRange(ConstraintFactory constraintFactory) { return constraintFactory.from(Employee.class) .filter(employee -> employee.getAssignedJobs().size() < 10 || employee.getAssignedJobs().size() > 30) .penalize("Employee job count out of range", HardSoftScore.ONE_HARD, employee -> Math.abs(employee.getAssignedJobs().size() - 20)); }
3. 员工总工时不超限
给Employee添加总工时派生属性,再编写约束:
// Employee类中添加总工时计算 public int getTotalWorkHours() { return getAssignedJobs().stream() .mapToInt(Job::getWorkHours) .sum(); } // 约束规则 @Constraint public Constraint employeeTotalHoursLimit(ConstraintFactory constraintFactory) { return constraintFactory.from(Employee.class) .filter(employee -> employee.getTotalWorkHours() > employee.getMaxWorkHours()) .penalize("Employee total hours exceed limit", HardSoftScore.ONE_HARD, employee -> employee.getTotalWorkHours() - employee.getMaxWorkHours()); }
额外注意事项
- 若使用OptaPlanner 8.2以下版本,不支持
@PlanningListVariable,需调整建模思路:将Employee设为规划实体,给每个Employee分配Vehicle,Vehicle的员工集合改为从Employee的分配结果聚合生成,避免直接用集合作为规划变量。 - 所有派生属性(如
assignedJobs、totalWorkHours)无需添加规划注解,仅作为约束计算的辅助字段。
内容的提问来源于stack exchange,提问作者Scott A. Levinson
相关产品推荐
相关产品推荐

