目前我正在做连续计划,我有两个实体,一个是机器,另一个是订单。该机器包含一个规划列表变量,而订单有一个指向该机器的逆阴影变量。我想添加一个内置的硬约束来限制特定订单可以进入哪些机器,但是我不能在机器实体中使用ValueRangeProvider来过滤订单列表,因为它不能在实体中使用。还有别的办法吗?提前感谢
事实上,依赖于实体的值范围不适用于规划列表变量。在不久的将来没有计划支持它。
您仍然可以通过使用过滤移动选择来实现所需的内置硬约束。
您通常需要三个SelectionFilter
实现,每个移动类型一个。我假设您想使用构建启发式阶段,其中包含ListAssignMove
,并且您希望在本地搜索阶段同时包含ListChangeMove
和ListSwapMove
。
然后,你需要一个高级的求解器配置来应用这些过滤器。
我在TaskAssignment示例中尝试了这种方法,以取代TaskAssigningConstraintProvider
中的noMissingSkills
约束,并使用移动过滤使其成为内置的硬约束。这就是我最后的结果:
过滤器如果您只是将Employee
更改为Machine
,Task
更改为Order
并重命名isTaskAllowed()
以更好地适合您的域,这些也应该适用于您的情况。
public class TaskAssignMoveFilter implements SelectionFilter<TaskAssignment, ListAssignMove<TaskAssignment>> {
@Override
public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListAssignMove<TaskAssignment> move) {
return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
}
}
public class TaskChangeMoveFilter implements SelectionFilter<TaskAssignment, ListChangeMove<TaskAssignment>> {
@Override
public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListChangeMove<TaskAssignment> move) {
return ((Employee) move.getDestinationEntity()).isTaskAllowed(((Task) move.getMovedValue()));
}
}
public class TaskSwapMoveFilter implements SelectionFilter<TaskAssignment, ListSwapMove<TaskAssignment>> {
@Override
public boolean accept(ScoreDirector<TaskAssignment> scoreDirector, ListSwapMove<TaskAssignment> move) {
return ((Employee) move.getLeftEntity()).isTaskAllowed(((Task) move.getRightValue())) &&
((Employee) move.getRightEntity()).isTaskAllowed(((Task) move.getLeftValue()));
}
}
Employee
上的新isTaskAllowed()
方法
这实现了硬约束。替换逻辑以拒绝不能分配给给定Machine
的Order
。
@PlanningEntity
public class Employee extends AbstractPersistable implements Labeled {
...
public boolean isTaskAllowed(Task task) {
return skillSet.containsAll(task.getTaskType().getRequiredSkillList());
}
...
}
解算器配置
基本上是复制粘贴。只要改变variableName
属性值(我猜是"orders"
)和过滤器的类名。
<constructionHeuristic>
<queuedValuePlacer>
<valueSelector id="1" variableName="tasks"/>
<changeMoveSelector>
<filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskAssignMoveFilter</filterClass>
<valueSelector mimicSelectorRef="1"/>
</changeMoveSelector>
</queuedValuePlacer>
</constructionHeuristic>
<localSearch>
<unionMoveSelector>
<changeMoveSelector>
<filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskChangeMoveFilter</filterClass>
</changeMoveSelector>
<swapMoveSelector>
<filterClass>org.optaplanner.examples.taskassigning.domain.solver.TaskSwapMoveFilter</filterClass>
</swapMoveSelector>
</unionMoveSelector>
</localSearch>