Optaplanner:基于 PlanningSolution 动态定义约束 属性
Optaplanner: Define constraints dynamically based on PlanningSolution property
假设我 this 实现了 ConstraintProvider
。
package com.example.solver;
import com.example.domain.Lesson;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import org.optaplanner.core.api.score.stream.Joiners;
public class TimeTableConstraintProvider implements ConstraintProvider {
@Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[] {
roomConflict(constraintFactory),
teacherConflict(constraintFactory),
};
}
private Constraint roomConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Lesson.class)
.join(Lesson.class,
Joiners.equal(Lesson::getTimeslot),
Joiners.equal(Lesson::getRoom),
Joiners.lessThan(Lesson::getId))
.penalize("Room conflict", HardSoftScore.ONE_HARD);
}
private Constraint teacherConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Lesson.class)
.join(Lesson.class,
Joiners.equal(Lesson::getTimeslot),
Joiners.equal(Lesson::getTeacher),
Joiners.lessThan(Lesson::getId))
.penalize("Teacher conflict", HardSoftScore.ONE_HARD);
}
假设我只想使用 roomConflict
进行约束,以防我的 PlanningSolution
具有布尔值 属性 considerRoomConflict
。同样,我只想使用 roomConflict
以防我的 PlanningSolution
具有布尔值 属性 considerTeacherConflict
。
假设我有 5 个这样的条件。什么是好的实施方式?
将 @ConstraintConfiguration
与 @ConstraintWeight
结合使用。一些 optaplanner-examples 使用它。
@ConstraintWeight("Teacher conflict")
// To disable, change to HardSoftScore.ZERO
private HardSoftScore teacherConflict = HardSoftScore.ONE_HARD;
然后使用penalizeConfigurable()
代替penalize()
:
constraintFactory.from(Lesson.class)
.join(...)
.penalizeConfigurable("Teacher conflict")
假设我 this 实现了 ConstraintProvider
。
package com.example.solver;
import com.example.domain.Lesson;
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
import org.optaplanner.core.api.score.stream.Constraint;
import org.optaplanner.core.api.score.stream.ConstraintFactory;
import org.optaplanner.core.api.score.stream.ConstraintProvider;
import org.optaplanner.core.api.score.stream.Joiners;
public class TimeTableConstraintProvider implements ConstraintProvider {
@Override
public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[] {
roomConflict(constraintFactory),
teacherConflict(constraintFactory),
};
}
private Constraint roomConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Lesson.class)
.join(Lesson.class,
Joiners.equal(Lesson::getTimeslot),
Joiners.equal(Lesson::getRoom),
Joiners.lessThan(Lesson::getId))
.penalize("Room conflict", HardSoftScore.ONE_HARD);
}
private Constraint teacherConflict(ConstraintFactory constraintFactory) {
return constraintFactory.from(Lesson.class)
.join(Lesson.class,
Joiners.equal(Lesson::getTimeslot),
Joiners.equal(Lesson::getTeacher),
Joiners.lessThan(Lesson::getId))
.penalize("Teacher conflict", HardSoftScore.ONE_HARD);
}
假设我只想使用 roomConflict
进行约束,以防我的 PlanningSolution
具有布尔值 属性 considerRoomConflict
。同样,我只想使用 roomConflict
以防我的 PlanningSolution
具有布尔值 属性 considerTeacherConflict
。
假设我有 5 个这样的条件。什么是好的实施方式?
将 @ConstraintConfiguration
与 @ConstraintWeight
结合使用。一些 optaplanner-examples 使用它。
@ConstraintWeight("Teacher conflict")
// To disable, change to HardSoftScore.ZERO
private HardSoftScore teacherConflict = HardSoftScore.ONE_HARD;
然后使用penalizeConfigurable()
代替penalize()
:
constraintFactory.from(Lesson.class)
.join(...)
.penalizeConfigurable("Teacher conflict")