如何设置OptaPlanner中Request的EntityList按ID正序排列?
问题描述
我有两个标注@PlanningEntity的类:Entity和Request,二者关联方式如下:
Request类代码
public class Request { @PlanningListVariable private List<Entity> EntityList; }
Entity类代码
public class Entity{ @InverseRelationShadowVariable(sourceVariableName = "EntityList") private Request Request; }
Solution类结构
public class Solution implements Serializable { @PlanningId private Long id; @PlanningEntityCollectionProperty private List<Request> RequestList; @ValueRangeProvider @ProblemFactCollectionProperty private List<Entity> Entities; }
我期望解决方案中RequestList里的每个Request的EntityList按ID正序排列,但实际结果始终是倒序。尝试添加约束限制顺序但未生效,请问该如何设置实现需求?
解决方案
1. 修正约束逻辑
如果之前的约束未生效,大概率是逻辑未覆盖所有相邻元素的顺序检查。正确的硬约束写法如下,强制列表中每个相邻元素都按ID正序排列:
private Constraint enforceEntityListOrder(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Request.class) .flatMap(request -> { List<Entity> entityList = request.getEntityList(); List<Tuple<Entity, Entity>> adjacentPairs = new ArrayList<>(); for (int i = 0; i < entityList.size() - 1; i++) { adjacentPairs.add(Tuple.of(entityList.get(i), entityList.get(i+1))); } return adjacentPairs.stream(); }) .filter(pair -> pair.getFirst().getId() > pair.getSecond().getId()) .penalize("Entity list out of order", HardSoftScore.ONE_HARD); }
2. 用软约束引导排序(推荐)
若硬约束导致规划无解,可改用软约束引导规划器生成正序列表,既保证解的可行性,又能趋近目标顺序:
private Constraint rewardEntityListOrder(ConstraintFactory constraintFactory) { return constraintFactory.forEach(Request.class) .flatMap(request -> { List<Entity> entityList = request.getEntityList(); List<Tuple<Entity, Entity>> adjacentPairs = new ArrayList<>(); for (int i = 0; i < entityList.size() - 1; i++) { adjacentPairs.add(Tuple.of(entityList.get(i), entityList.get(i+1))); } return adjacentPairs.stream(); }) .filter(pair -> pair.getFirst().getId() < pair.getSecond().getId()) .reward("Entity in correct order", HardSoftScore.ONE_SOFT); }
3. 配置列表变量的排序策略
直接在@PlanningListVariable注解中指定比较器,让规划器分配元素时优先按ID正序选择,从根源上减少逆序:
public class Request { @PlanningListVariable(valueRangeProviderRefs = "Entities", comparator = EntityByIdComparator.class) private List<Entity> EntityList; } // 自定义比较器类 public class EntityByIdComparator implements Comparator<Entity>, Serializable { @Override public int compare(Entity e1, Entity e2) { return Long.compare(e1.getId(), e2.getId()); } }
4. 规划后主动排序(兜底)
如果上述方法均不生效,可在获取最终解决方案后,对每个Request的EntityList手动排序:
Solution bestSolution = solver.getBestSolution(); bestSolution.getRequestList().forEach(request -> { request.getEntityList().sort(Comparator.comparing(Entity::getId)); });
内容的提问来源于stack exchange,提问作者romee
相关产品推荐
相关产品推荐

