OptaPlanner,显示排除的解决方案
OptaPlanner, excluded solution shows up
请通过这个简单的任务分配项目帮助我理解 DRL。 2 个工人 id=1 和 2,3 个任务 id=1,2,3,每个任务的持续时间以秒为单位。任务 1 和 3 的持续时间比任务 2 多一点。开始时我使用以下规则(只有一个规则)试图平衡每个工人的总时间,所以我希望一个工人完成任务 1 和 3,而另一个则需要任务 2.
rule "fairness"
when
$worker: Worker()
accumulate(
Task(worker == $worker, $d: durationInSec);
$s: sum($d*$d)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, -$s.longValue());
end
结果是所有任务总是分配给工作人员 1。我想调试这个问题并将上面的规则替换为以下 2 条规则:
rule "A"
when
$worker: Worker(id == 1) // for worker 1
then
scoreHolder.addHardConstraintMatch(kcontext, -1); // hard score -1
end
rule "B"
when
$worker: Worker(id == 2) // for worker 2
then
scoreHolder.addSoftConstraintMatch(kcontext, 1); // soft score +1
end
我以为工人 1 会因为规则“A”而被排除在外,但结果仍然是,工人 1 获得了所有 3 个任务,输出如下:
o.o.c.i.l.DefaultLocalSearchPhase : Local Search phase (1) ended: time spent (30001), best score (-3hard/3soft), score calculation speed (7309/sec), step total (12948).
o.o.core.impl.solver.DefaultSolver: Solving ended: time spent (30002), best score (-3hard/3soft), score calculation speed (7258/sec), phase total (2), environment mode (NON_REPRODUCIBLE)
我希望工人 2 完成所有 3 个任务,分数为 0hard/3soft。以下是我的部分解决方案class,问题出在哪里?
@PlanningSolution
@Entity
public class Solution {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private SolverStatus solverStatus;
@PlanningScore
private HardSoftLongScore score;
@ProblemFactCollectionProperty
@OneToMany
@ValueRangeProvider(id = "workerRange")
private List<Worker> workerList;
@PlanningEntityCollectionProperty
@OneToMany
private List<Task> taskList;
...
@Entity
@PlanningEntity
public class Task implements Comparable<Task> {
@PlanningId
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(cascade=CascadeType.ALL)
@PlanningVariable(valueRangeProviderRefs = "workerRange")
private Worker worker;
当在 RHS 中放置 println 时,我确实看到 worker 1 和 2 都被打印出来了:
System.out.println("worker=" + $worker.toString() + ", task=" + $tb.toString() + "; " +
scoreHolder.getHardScore() + "hard/" + scoreHolder.getHardScore() + "soft");
...
worker=1, task=2; -3hard/-3soft
worker=1, task=1; -3hard/-3soft
worker=2, task=3; -3hard/-3soft
worker=2, task=2; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
worker=1, task=3; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
...
规则“A”和“B”penalize/reward纯粹是为了这两个工人的存在,他们没有说任何分配给他们的任务。
乍一看,我没有发现第一个约束(“公平”)有什么问题。您始终可以在规则的 then
部分添加 System.out.println(...)
以对其进行调试。
或者,如果您更喜欢 Java 而不是 DRL,也许 ConstraintStreams API 对您来说可能会很有趣。
请通过这个简单的任务分配项目帮助我理解 DRL。 2 个工人 id=1 和 2,3 个任务 id=1,2,3,每个任务的持续时间以秒为单位。任务 1 和 3 的持续时间比任务 2 多一点。开始时我使用以下规则(只有一个规则)试图平衡每个工人的总时间,所以我希望一个工人完成任务 1 和 3,而另一个则需要任务 2.
rule "fairness"
when
$worker: Worker()
accumulate(
Task(worker == $worker, $d: durationInSec);
$s: sum($d*$d)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, -$s.longValue());
end
结果是所有任务总是分配给工作人员 1。我想调试这个问题并将上面的规则替换为以下 2 条规则:
rule "A"
when
$worker: Worker(id == 1) // for worker 1
then
scoreHolder.addHardConstraintMatch(kcontext, -1); // hard score -1
end
rule "B"
when
$worker: Worker(id == 2) // for worker 2
then
scoreHolder.addSoftConstraintMatch(kcontext, 1); // soft score +1
end
我以为工人 1 会因为规则“A”而被排除在外,但结果仍然是,工人 1 获得了所有 3 个任务,输出如下:
o.o.c.i.l.DefaultLocalSearchPhase : Local Search phase (1) ended: time spent (30001), best score (-3hard/3soft), score calculation speed (7309/sec), step total (12948).
o.o.core.impl.solver.DefaultSolver: Solving ended: time spent (30002), best score (-3hard/3soft), score calculation speed (7258/sec), phase total (2), environment mode (NON_REPRODUCIBLE)
我希望工人 2 完成所有 3 个任务,分数为 0hard/3soft。以下是我的部分解决方案class,问题出在哪里?
@PlanningSolution
@Entity
public class Solution {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private SolverStatus solverStatus;
@PlanningScore
private HardSoftLongScore score;
@ProblemFactCollectionProperty
@OneToMany
@ValueRangeProvider(id = "workerRange")
private List<Worker> workerList;
@PlanningEntityCollectionProperty
@OneToMany
private List<Task> taskList;
...
@Entity
@PlanningEntity
public class Task implements Comparable<Task> {
@PlanningId
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(cascade=CascadeType.ALL)
@PlanningVariable(valueRangeProviderRefs = "workerRange")
private Worker worker;
当在 RHS 中放置 println 时,我确实看到 worker 1 和 2 都被打印出来了:
System.out.println("worker=" + $worker.toString() + ", task=" + $tb.toString() + "; " +
scoreHolder.getHardScore() + "hard/" + scoreHolder.getHardScore() + "soft");
...
worker=1, task=2; -3hard/-3soft
worker=1, task=1; -3hard/-3soft
worker=2, task=3; -3hard/-3soft
worker=2, task=2; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
worker=1, task=3; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
worker=2, task=1; -3hard/-3soft
...
规则“A”和“B”penalize/reward纯粹是为了这两个工人的存在,他们没有说任何分配给他们的任务。
乍一看,我没有发现第一个约束(“公平”)有什么问题。您始终可以在规则的 then
部分添加 System.out.println(...)
以对其进行调试。
或者,如果您更喜欢 Java 而不是 DRL,也许 ConstraintStreams API 对您来说可能会很有趣。