[英]How to apply overconstrained planning in OptaPlanner in a better way?
[英]Overconstrained planning not working as expected
我一直试图让过度约束的计划适合我的情况,但仍然遇到一些失败的硬约束仍然被分配的问题。 抱歉,如果之前已经回答过这个问题,但是我看到的大多数示例/解决方案都以 Drools 为中心,我在这个项目中使用流 API。 如果有帮助,请使用 optaplanner 的 quarkus 1.4.2 实现。
以下是我要完成的一些示例限制:
private Constraint unnassignedPerson(ConstraintFactory constraintFactory) {
return constraintFactory.from(Assignment.class)
.filter(assignment -> assignment.getPerson() == null)
.penalize("Unassigned", HardMediumSoftScore.ONE_MEDIUM);
private Constraint numberAssignmentConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Assignment.class)
.join(Assignment.class,
Joiners.equal(Assignment::getPerson),
Joiners.equal(Assignment::getNumber),
Joiners.lessThan(Assignment::getId))
.penalize("Number Conflict", HardMediumSoftScore.of(2, 0, 0));
private Constraint tooLittleSpaceBetweenResourceAssignment(ConstraintFactory constraintFactory) {
return constraintFactory.from(Assignment.class)
.join(Assignment.class, Joiners.equal(Assignment::getPerson), Joiners.lessThan(Assignment::getId))
.filter((assignment, assignment2) -> !assignment.getResourceId().equals(assignment2.getResourceId()))
.filter(((assignment, assignment2) -> inRange(1, assignment.getNumber(), assignment2.getNumber())))
.penalize("Not enough space between assignments of different resource (requires 1)", HardMediumSoftScore.of(1, 0, 0));
}
(inRange 是一个简单的局部 function 来获取两个数字之间的绝对差)
请注意,在尊重可为空的计划变量方面,它们彼此独立工作 - 只有当两者都启用时,我才会得到意想不到的结果。 当两者都启用时,尽管在调试日志中显示为硬约束(在我的本地测试中总是以 -12hard/-2medium/0soft 结束),但仍会在解决方案中分配具有较低硬分的那个。
任何关于我可能做错了什么的见解将不胜感激,并在此先感谢:)
作为后续,看来我的分配冲突约束的Joiners.lessThan(Assignment::getId)
部分与可为空的分配不兼容。 我删除了它并添加了一些更明确的检查,现在一切正常:D
对任何可能有帮助的人的伪适应:
private Constraint numberAssignmentConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Assignment.class)
.join(Assignment.class,
Joiners.equal(Assignment::getPerson),
Joiners.equal(Assignment::getNumber))
.filter(((assignment, assignment2) -> assignment.getPerson() != null && assignment2.getPerson() != null))
.filter(((assignment, assignment2) -> !assignment.getId().equals(assignment2.getId())))
.penalize("Number Conflict", HardMediumSoftScore.of(2, 0, 0));
}
第一个约束不是必须是fromUnfiltered(Assignment.class)
而不是from(Assignment.class)
。 我相信from()
不会传递具有未分配计划变量的实体,因此永远不会应用 ONE_MEDIUM 惩罚?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.