[英]Optaplanner: Drools rule not firing during solving, only after
我正在使用類似於optaplanner中護士計划示例的求解程序(將雇員分配到輪班中,雇員是計划變量,對計划實體進行輪班),不同的是輪班分為1小時間隔,並且每個員工可以進行多個輪班天。
硬約束之一是每個員工每個月只能工作一定的時間。 我目前使用以下規則對此建模,並且可以正常工作:
rule "At most 173h work per month per fulltime employee, assuming roster is only for 1 month"
when
$e: Employee(type == EmployeeType.FULLTIME)
$total : Number(intValue() > 10320)
from accumulate(
Shift(employee == $e,
$minutes : getTimeSlot().getMinutesInterval()),
sum($minutes))
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
現在,由於預計需要計划很多輪班(1000多個),因此我認為可以通過跟蹤每個員工的工作時間來加快處理速度。
為此,我給每個員工一個對象(統計信息),該對象應跟蹤此信息。 該對象在Shift對象的setEmployee方法期間進行更新,如下所示:
public void setEmployee(Employee employee) {
if(this.employee != null){
this.employee.getStats().subtractWorkedMinutes(this.timeSlot);
}
this.employee = employee;
if(this.employee != null){
this.employee.getStats().addWorkedMinutes(this.timeSlot);
}
}
我還像在護士調度示例中一樣實現了EmployeeChangeMove和ShiftAssignmentSwapMove,以確保每次移動都調用setEmployee()方法,因此應更改員工統計信息。 現在,我想在規則中使用這些增量計算的員工統計信息,如下所示:
rule "At most 173h work per month per fulltime employee, assuming roster is only for 1 month"
when
Employee(type == EmployeeType.FULLTIME,
getStats().getTotalMinutesWorked() > 10320)
then
scoreHolder.addHardConstraintMatch(kcontext, -1);
end
但是,我遇到的問題是,這些規則在求解過程中永遠不會觸發,並且求解器沒有考慮這些因素來計算分數。 只有在求解器完成並且從解決方案中生成新的ScoreDirector以獲得ConstraintMatchTotal對象之后,該規則才實際觸發,並且確實顯示為違反的規則。
我究竟做錯了什么?
在求解過程中跟蹤約束變量以在約束規則中使用變量的最佳方法是什么?
當OptaPlanner修改Shift.employee時,Drools得知Shift已修改(因此它可以進行增量增量得分計算)。 Drools沒有被告知Employee也被修改了...
解決方案:使Employee.stats成為影子變量。
Employee應該是一個影子@PlanningEntity
,它的stats字段應該是一個@CustomShadowVariable
,其源是setEmployee Shift.employee
,其偵聽器在Shift.setEmployee
執行代碼,以便setEmployee可以再次成為一個簡單的setter。
除非正在進行掃描,否則不要忘記在求解器配置中將Employee注冊為計划實體。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.