Optaplanner:添加新约束(硬)

时间:2014-10-22 21:25:29

标签: java scheduling project-planning optaplanner rostering

我最近一直在熟悉Optaplanner - 更具体地说,就是护士排班的例子 - 而且一直试图增加一个新的硬约束,但到目前为止,还没有取得多大成功。

我正在努力添加DayUnavailableRequest约束(即员工无法在特定日期工作)。我使用DayOffRequest作为模板。两个约束之间的唯一区别是DayUnavailableRequest约束将是" hard"。

为此,我在请求文件夹中添加了一个新文件 - DayUnavailableRequest.Java:

package org.optaplanner.examples.nurserostering.domain.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;

import org.optaplanner.examples.common.domain.AbstractPersistable;
import org.optaplanner.examples.nurserostering.domain.Employee;
import org.optaplanner.examples.nurserostering.domain.ShiftDate;

@XStreamAlias("DayUnavailableRequest")
public class DayUnavailableRequest extends AbstractPersistable {

private Employee employee;
private ShiftDate shiftDate;

public Employee getEmployee() {
    return employee;
}

public void setEmployee(Employee employee) {
    this.employee = employee;
}

public ShiftDate getShiftDate() {
    return shiftDate;
}

public void setShiftDate(ShiftDate shiftDate) {
    this.shiftDate = shiftDate;
}

@Override
public String toString() {
    return shiftDate + "_OFF_" + employee;
}

}

然后我将以下内容添加到nurseRosteringScoreRules.drl:

Availability day on/off
rule "dayUnavailableRequest"
when
    $dayUnavailableRequest : DayUnavailableRequest($employee : employee, $shiftDate :  shiftDate)
    $assignment : ShiftAssignment(employee == $employee, shiftDate == $shiftDate)
then
    scoreHolder.addHardConstraintMatch(kcontext, - 1);
end`

在nurseRoster.java中,我补充道:

public List<DayUnavailableRequest> getDayUnavailableRequestList() {
return dayUnavailableRequestList;
}

public void setDayUnavailableRequestList(List<DayUnavailableRequest> dayUnavailableRequestList) {
    this.dayUnavailableRequestList = dayUnavailableRequestList;
}    

以及:

facts.addAll(dayUnavailableRequestList);

在Employee.java中,我补充道:

private Map<ShiftDate, DayUnavailableRequest> dayUnavailableRequestMap;

和...

public Map<ShiftDate, DayUnavailableRequest> getDayUnavailableRequestMap() {
    return dayUnavailableRequestMap;
}

public void setDayUnavailableRequestMap(Map<ShiftDate, DayUnavailableRequest> dayUnavailableRequestMap) {
    this.dayUnavailableRequestMap = dayUnavailableRequestMap;
}

最后,在NurseRosteringImporter.java中,我包括:

第115行:

readShiftOnRequestList(nurseRoster, schedulingPeriodElement.getChild("ShiftOnRequests"));

第131行:

nurseRoster.getDayUnavailableRequestList().size(),

和...

private void readDayUnavailableRequestList(NurseRoster nurseRoster, Element dayUnavailableRequestsElement) throws JDOMException {
        List<DayUnavailableRequest> dayUnavailableRequestList;
        if (dayUnavailableRequestsElement == null) {
            dayUnavailableRequestList = Collections.emptyList();
        } else {
            List<Element> dayUnavailableElementList = (List<Element>) dayUnavailableRequestsElement.getChildren();
            dayUnavailableRequestList = new ArrayList<DayUnavailableRequest>(dayUnavailableElementList.size());
            long id = 0L;
            for (Element element : dayUnavailableElementList) {
                assertElementName(element, "DayUnavailable");
                DayUnavailableRequest dayUnavailableRequest = new DayUnavailableRequest();
                dayUnavailableRequest.setId(id);

                Element employeeElement = element.getChild("EmployeeID");
                Employee employee = employeeMap.get(employeeElement.getText());
                if (employee == null) {
                    throw new IllegalArgumentException("The shiftDate (" + employeeElement.getText()
                            + ") of dayUnavailableRequest (" + dayUnavailableRequest + ") does not exist.");
                }
                dayUnavailableRequest.setEmployee(employee);

                Element dateElement = element.getChild("Date");
                ShiftDate shiftDate = shiftDateMap.get(dateElement.getText());
                if (shiftDate == null) {
                    throw new IllegalArgumentException("The date (" + dateElement.getText()
                            + ") of dayUnavailableRequest (" + dayUnavailableRequest + ") does not exist.");
                }
                dayUnavailableRequest.setShiftDate(shiftDate);

                dayUnavailableRequestList.add(dayUnavailableRequest);
                employee.getDayUnavailableRequestMap().put(shiftDate, dayUnavailableRequest);
                id++;
            }
        }
        nurseRoster.setDayUnavailableRequestList(dayUnavailableRequestList);
    }

我使用sprint01_1week.xml进行测试。当我添加约束数据时,我收到错误,或者应用程序正常工作,但可用性约束本身不会生效。

例如:

<DaysUnavailable>   
 <DayUnavailable>
  <EmployeeID>4</EmployeeID>
  <Date>2014-10-24</Date>
 </DayUnavailable>
</DaysUnavailable>

返回一个很长的&#34;未捕获的异常&#34;错误。

<DayUnavailableRequest>
 <DayUnavailable>
  <EmployeeID>4</EmployeeID>
  <Date>2014-10-24</Date>
 </DayUnavailable>
</DayUnavailableRequest>  

不会返回错误,但也不会应用于该应用程序。

非常感谢任何帮助。此外,如果有更有效的方式来添加员工可用性,请分享。

感谢。

2 个答案:

答案 0 :(得分:0)

您在NurseRosteringImporter.java中添加了

第115行:

readShiftOnRequestList(nurseRoster, schedulingPeriodElement.getChild("ShiftOnRequests"));

你必须添加它,而不是:

readDayUnavailableRequestList(nurseRoster, schedulingPeriodElement.getChild("DayUnavailableRequest"));

答案 1 :(得分:-1)

777的在线NurseRosteringImporter.java,您需要添加与行776775773等相同的行,但是DayUnavailableRequest 1}}。

你也需要做上面提到的那个人。

这些变化对我有用。