使用标准配置的Nearby Selection无法选择正确目标,出现类型转换异常
看起来你遇到的类型转换问题,核心是Nearby Selection的配置和你的实体模型不匹配,尤其是目标选择器的类型和距离度量类的配置出错了。咱们一步步拆解问题,帮你定位修复:
1. 配置中误用了示例的距离度量类
你自己已经实现了适配业务的TaskNerbyDistanceMeter(拼写小失误,不过不影响功能),但在solve配置里,所有nearbySelection节点的nearbyDistanceMeterClass都指向了OptaPlanner官方示例里的CustomerNearbyDistanceMeter——这个类的泛型是针对车辆路径问题的Customer和Vehicle,和你的Task、Risorsa完全不匹配,这会直接导致OptaPlanner在计算距离时出现类型混乱。
你需要把所有配置里的这个类路径替换成你自己的实现:
<nearbyDistanceMeterClass>org.digimark.planner.domain.scheduler.TaskNerbyDistanceMeter</nearbyDistanceMeterClass>
2. ListChangeMoveSelector的目标选择器类型错误
你的业务模型是:Risorsa作为规划实体,拥有@PlanningListVariable标注的Task列表;Task是影子变量关联到Risorsa。而listChangeMoveSelector的作用是把一个Task移动到某个Risorsa的任务列表中,因此:
valueSelector选择要移动的Task(这部分你的配置是对的)destinationSelector必须选择目标Risorsa实体,而不是另一个Task
但你当前的配置里,nearbySelection没有明确指定目标实体类型,OptaPlanner错误地默认选择了和源(Task)同类型的对象作为目标,这就是为什么会出现Task强制转换为Risorsa的异常。
修正后的listChangeMoveSelector配置应该明确指定目标是Risorsa:
<listChangeMoveSelector> <valueSelector id="valueSelector1"/> <destinationSelector> <nearbySelection> <originValueSelector mimicSelectorRef="valueSelector1"/> <!-- 明确指定目标选择器是Risorsa实体 --> <destinationEntitySelector> <entityClass>org.digimark.planner.domain.resources.Risorsa</entityClass> </destinationEntitySelector> <nearbyDistanceMeterClass>org.digimark.planner.domain.scheduler.TaskNerbyDistanceMeter</nearbyDistanceMeterClass> <parabolicDistributionSizeMaximum>40</parabolicDistributionSizeMaximum> </nearbySelection> </destinationSelector> </listChangeMoveSelector>
3. 额外的优化建议
你的TaskNerbyDistanceMeter逻辑是完全匹配部门和技能就返回0,否则返回Double.MAX_VALUE,这相当于只筛选完全符合条件的Risorsa。如果业务允许,你可以调整距离计算逻辑,比如匹配部门得1分、匹配技能得1分,总距离越低优先级越高,这样Nearby Selection能提供更灵活的候选集,提升求解效果。
另外,你配置里的listSwapMoveSelector是用来交换两个Task的位置,你需要确认这个操作在你的业务场景中是否合理(比如调整同一个Risorsa下的任务顺序,或者跨资源交换任务),如果需要保留,也要确保它的nearbySelection配置和你的实体类型匹配。
备注:内容来源于stack exchange,提问作者Andrea Perdonò

