连续和实时计划更新问题

时间:2019-06-23 22:42:25

标签: java optaplanner

尽管所有其他要素(模式)(包括请求)都在更新,但我没有看到轮班分配提前正确更新。我正在为12名员工运行14天的轮班花名册。 11必须每两周工作9天1必须每两周工作5天。 (104班)。谁能看到我的代码和/或方法有任何明显的错误。仅供参考,我尝试了所有不同的加权方法。

我已经基于网球示例实现了负载平衡解决方案。这对于所有全职工作9个班次(108个班次)的员工来说非常有用。所有元素均正确更新。请求,不需要的模式等,并且进展良好。维护所有模式,请求和轮班要求

private void advancePlanningWindowStart() {
        logger.info("Advancing planningWindowStart.");
        if (solutionBusiness.isSolving()) {
            JOptionPane.showMessageDialog(this.getTopLevelAncestor(),
                    "The GUI does not support this action yet during solving.\nOptaPlanner itself does support it.\n"
                            + "\nTerminate solving first and try again.",
                    "Unsupported in GUI", JOptionPane.INFORMATION_MESSAGE);
            return;
        }

        doProblemFactChange(scoreDirector -> {
            NurseRoster nurseRoster = scoreDirector.getWorkingSolution();
            NurseRosterParametrization nurseRosterParametrization = nurseRoster
                    .getNurseRosterParametrization();

            List<ShiftDate> shiftDateList = nurseRoster.getShiftDateList();

            Shift oldLastShift = nurseRoster.getShiftList()
                    .get(nurseRoster.getShiftList().size() - 1);
            long shiftId = oldLastShift.getId() + 1L;
            int shiftIndex = oldLastShift.getIndex() + 1;
            ShiftDate oldLastShiftDate = shiftDateList
                    .get(shiftDateList.size() - 1);
            long shiftDateId = (oldLastShiftDate.getId() + 1L);
            int shiftDayIndex = (oldLastShiftDate.getDayIndex() + 1);

            scoreDirector
                    .beforeProblemPropertyChanged(nurseRosterParametrization);

            // Update to get the first day along with adding 14 days to the run
            LocalDate startDate = (oldLastShiftDate.getDate().plusDays(1));
            LocalDate endDate = (oldLastShiftDate.getDate().plusDays(14));
            int maxDayIndex = Math.toIntExact(DAYS.between(startDate, endDate));
            int shiftDateSize = maxDayIndex + 1;
            List<ShiftDate> newshiftdateList = new ArrayList<>(shiftDateSize);
            shiftDateMap = new HashMap<>(shiftDateSize);
            LocalDate date = startDate;
            for (int i = 0; i < shiftDateSize; i++) {
                ShiftDate shiftDate = new ShiftDate();
                shiftDate.setId(shiftDateId);
                shiftDate.setDayIndex(shiftDayIndex);
                shiftDate.setDate(date);
                shiftDate.setShiftList(new ArrayList<>());
                shiftDateMap.put(date, shiftDate);
                shiftDateId++;
                shiftDayIndex++;
                date = date.plusDays(1);
                nurseRoster.getShiftDateList().add(shiftDate);
                newshiftdateList.add(shiftDate);
                scoreDirector.afterProblemFactAdded(shiftDate);

            }

            List<Skill> skillList;

            List<Skill> skillElementList = (List<Skill>) nurseRoster
                    .getSkillList();
            skillList = new ArrayList<>(skillElementList.size());
            skillMap = new HashMap<>(skillElementList.size());

            for (Skill element : skillElementList) {
                Skill skill = new Skill();
                long skillid = element.getId();
                skill.setId(skillid);
                skill.setCode(element.getCode());
                Skill skillnew = scoreDirector.lookUpWorkingObject(skill);
                skillList.add(skillnew);
                if (skillMap.containsKey(skillnew.getCode())) {
                    throw new IllegalArgumentException(
                            "There are 2 skills with the same code ("
                                    + skill.getCode() + ").");
                }
                skillMap.put(skillnew.getCode(), skillnew);

            }

            List<Contract> contractElementList = (List<Contract>) nurseRoster
                    .getContractList();

            List<Contract> contractList = new ArrayList<>(
                    contractElementList.size());

            contractMap = new HashMap<>(contractElementList.size());

            for (Contract element : contractElementList) {
                Contract contract = new Contract();
                long Id = element.getId();
                contract.setId(Id);
                contract.setCode(element.getCode());
                contract.setDescription(element.getDescription());
                WeekendDefinition weekend = element.getWeekendDefinition();
                contract.setWeekendDefinition(weekend);
                contract.setContractLineList(new ArrayList<ContractLine>());
                Contract contractnew = scoreDirector
                        .lookUpWorkingObject(contract);
                contractMap.put(contractnew.getCode(), contractnew);
                contractList.add(contractnew);

            }

            List<Employee> employeeElementList = (List<Employee>) nurseRoster
                    .getEmployeeList();
            Employee oldLastEmployee = nurseRoster.getEmployeeList()
                    .get(nurseRoster.getEmployeeList().size() - 1);
            long empId = oldLastEmployee.getId() + 1L;
            List<Employee> employeeList = new ArrayList<>(
                    employeeElementList.size());

            employeeMap = new HashMap<>(employeeElementList.size());

            for (Employee element : employeeElementList) {

                Employee employee = new Employee();
                String name = element.getName();
                String code = element.getCode();

                employee.setId(empId);
                empId++;
                Contract c = scoreDirector
                        .lookUpWorkingObject(element.getContract());
                employee.setCode(code);
                employee.setContract(c);
                employee.setName(name);

                employeeList.add(employee);

                employeeMap.put(employee.getName(), employee);
                scoreDirector.afterProblemFactAdded(employee);

            }

            List<ShiftTypeSkillRequirement> coverRequirementElementList = (List<ShiftTypeSkillRequirement>) nurseRoster
                    .getShiftTypeSkillRequirementList();
            List<ShiftType> shiftTypeElementList = (List<ShiftType>) nurseRoster
                    .getShiftTypeList();
            List<ShiftType> shiftTypeList = new ArrayList<>(
                    shiftTypeElementList.size());
            shiftTypeMap = new HashMap<>(shiftTypeElementList.size());
            int index = 0;
            long shiftTypeSkillRequirementId = 0L;
            List<ShiftTypeSkillRequirement> shiftTypeSkillRequirementList = new ArrayList<>(
                    shiftTypeElementList.size() * 2);

            for (ShiftType shiftelement : shiftTypeElementList) {

                ShiftType shiftType = new ShiftType();
                long Id = shiftelement.getId();
                shiftType.setId(Id);
                shiftType.setCode(shiftelement.getCode());
                shiftType.setIndex(index);
                String startTimeString = shiftelement.getStartTimeString();
                shiftType.setStartTimeString(startTimeString);
                String endTimeString = shiftelement.getEndTimeString();
                shiftType.setEndTimeString(endTimeString);
                shiftType
                        .setNight(startTimeString.compareTo(endTimeString) > 0);
                shiftType.setDescription(shiftelement.getDescription());
                ShiftType shiftTypenew = scoreDirector
                        .lookUpWorkingObject(shiftType);
                for (ShiftTypeSkillRequirement skillElement : coverRequirementElementList) {
                    ShiftTypeSkillRequirement shiftTypeSkillRequirement = new ShiftTypeSkillRequirement();
                    shiftTypeSkillRequirement
                            .setId(shiftTypeSkillRequirementId);
                    ShiftType shiftTypen = scoreDirector
                            .lookUpWorkingObject(shiftType);
                    shiftTypeSkillRequirement.setShiftType(shiftTypen);

                    Skill skill = skillMap
                            .get(skillElement.getSkill().getCode());
                    Skill skillnew = scoreDirector.lookUpWorkingObject(skill);
                    if (skillnew == null) {
                        throw new IllegalArgumentException("The skill ("
                                + skillElement.getSkill().getCode()
                                + ") of shiftType (" + shiftType.getCode()
                                + ") does not exist.");
                    }
                    shiftTypeSkillRequirement.setSkill(skillnew);
                    shiftTypeSkillRequirementList
                            .add(shiftTypeSkillRequirement);
                    shiftTypeSkillRequirementId++;
                }

                shiftTypeList.add(shiftTypenew);
                if (shiftTypeMap.containsKey(shiftTypenew.getCode())) {
                    throw new IllegalArgumentException(
                            "There are 2 shiftTypes with the same code ("
                                    + shiftTypenew.getCode() + ").");
                }
                shiftTypeMap.put(shiftTypenew.getCode(), shiftTypenew);

                index++;
            }
            nurseRoster.setShiftTypeList(shiftTypeList);
            nurseRoster.setShiftTypeSkillRequirementList(
                    shiftTypeSkillRequirementList);

            int shiftListSize = shiftDateMap.size() * shiftTypeList.size();

            List<Shift> shiftList1 = new ArrayList<>(shiftListSize);
            dateAndShiftTypeToShiftMap = new HashMap<>(shiftListSize);
            dayOfWeekAndShiftTypeToShiftListMap = new HashMap<>(
                    7 * shiftTypeList.size());

            for (ShiftDate shiftDate : newshiftdateList) {
                for (ShiftType shiftType : shiftTypeList) {
                    Shift shift = new Shift();
                    shift.setId(shiftId);
                    shift.setShiftDate(shiftDate);
                    shiftDate.getShiftList().add(shift);
                    ShiftType type = scoreDirector
                            .lookUpWorkingObject(shiftType);
                    shift.setShiftType(type);
                    shift.setIndex(shiftIndex);
                    shift.setRequiredEmployeeSize(0); // Filled in later
                    shiftList1.add(shift);
                    dateAndShiftTypeToShiftMap.put(
                            Pair.of(shiftDate.getDate(), type.getCode()),
                            shift);
                    addShiftToDayOfWeekAndShiftTypeToShiftListMap(shiftDate,
                            type, shift);
                    shiftId++;
                    shiftIndex++;
                    nurseRoster.getShiftList().add(shift);
                    scoreDirector.afterProblemFactAdded(shift);
                }

            }

            List<DayOffRequest> dayOffRequestList;

            List<DayOffDate> dayOffElementList = rosterService.listDayOffDate();

            dayOffRequestList = new ArrayList<>(dayOffElementList.size());
            long id = 0L;
            for (DayOffDate element : dayOffElementList) {
                DayOffRequest dayOffRequest = new DayOffRequest();

                dayOffRequest.setId(id);
                id++;
                int weight = element.getWeight();
                LocalDate shiftDate = element.getDate();

                ShiftDate dateoff = shiftDateMap.get(shiftDate);
                Employee employee = element.getEmployee();
                Employee workingEmployee = scoreDirector
                        .lookUpWorkingObject(employee);

                dayOffRequest.setWeight(weight);
                dayOffRequest.setEmployee(workingEmployee);
                dayOffRequest.setShiftDate(dateoff);

                dayOffRequestList.add(dayOffRequest);
                workingEmployee.getDayOffRequestMap().put(dateoff,
                        dayOffRequest);
                nurseRoster.getDayOffRequestList().add(dayOffRequest);

            }

            List<DayOnRequest> dayOnRequestList;

            List<DayOnDate> dayOnElementList1 = rosterService.listDayOnDate();
            long onid = 0L;
            dayOnRequestList = new ArrayList<>(dayOnElementList1.size());
            for (DayOnDate element : dayOnElementList1) {

                DayOnRequest dayOnRequest = new DayOnRequest();

                int weight = element.getWeight();
                LocalDate localshiftDate = element.getDate();

                ShiftDate dateon = shiftDateMap.get(localshiftDate);
                Employee employee = element.getEmployee();
                Employee workingEmployee = scoreDirector
                        .lookUpWorkingObject(employee);

                dayOnRequest.setId(onid);
                onid++;
                dayOnRequest.setWeight(weight);
                dayOnRequest.setEmployee(workingEmployee);
                dayOnRequest.setShiftDate(dateon);
                dayOnRequestList.add(dayOnRequest);
                workingEmployee.getDayOnRequestMap().put(dateon, dayOnRequest);
                nurseRoster.getDayOnRequestList().add(dayOnRequest);

            }

            List<ShiftOffRequest> shiftOffRequestList;

            List<ShiftOffDate> shiftOffElementList = (List<ShiftOffDate>) rosterService
                    .listShiftOffDate();
            shiftOffRequestList = new ArrayList<>(shiftOffElementList.size());
            for (ShiftOffDate element : shiftOffElementList) {

                ShiftOffRequest shiftOffRequest = new ShiftOffRequest();

                long ShiftonId = element.getId();
                int weight = element.getWeight();
                Employee employee = element.getEmployee();
                Employee workingEmployee = scoreDirector
                        .lookUpWorkingObject(employee);
                LocalDate date1 = element.getDate();

                String shiftcode = element.getShiftType().getCode();
                Shift shift = dateAndShiftTypeToShiftMap
                        .get(Pair.of(date1, shiftcode));

                shiftOffRequest.setId(ShiftonId);
                shiftOffRequest.setEmployee(workingEmployee);
                shiftOffRequest.setShift(shift);
                shiftOffRequest.setWeight(weight);
                shiftOffRequestList.add(shiftOffRequest);
                workingEmployee.getShiftOffRequestMap().put(shift,
                        shiftOffRequest);
                nurseRoster.setShiftOffRequestList(shiftOffRequestList);

            }

            List<ShiftOnRequest> shiftOnRequestList;

            List<ShiftOnDate> shiftOnElementList = (List<ShiftOnDate>) rosterService
                    .listShiftOnDate();
            shiftOnRequestList = new ArrayList<>(shiftOnElementList.size());
            for (ShiftOnDate element : shiftOnElementList) {

                ShiftOnRequest shiftOnRequest = new ShiftOnRequest();

                long ShiftonId = element.getId();
                int weight = element.getWeight();
                Employee employee = element.getEmployee();
                Employee workingEmployee = scoreDirector
                        .lookUpWorkingObject(employee);
                LocalDate date1 = element.getDate();
                String shiftcode = element.getShiftType().getCode();
                Shift shift = dateAndShiftTypeToShiftMap
                        .get(Pair.of(date1, shiftcode));

                shiftOnRequest.setId(ShiftonId);
                shiftOnRequest.setEmployee(workingEmployee);
                shiftOnRequest.setShift(shift);
                shiftOnRequest.setWeight(weight);
                shiftOnRequestList.add(shiftOnRequest);
                workingEmployee.getShiftOnRequestMap().put(shift,
                        shiftOnRequest);
                nurseRoster.setShiftOnRequestList(shiftOnRequestList);

            }

            List<CoverRequirements> coverRequirementElementList1 = (List<CoverRequirements>) rosterService
                    .listCoverRequirements();
            for (CoverRequirements element : coverRequirementElementList1) {
                String type = element.getShiftType().getCode();
                ShiftType shiftTypen = shiftTypeMap.get(type);
                DayOfWeek day = element.getDayOfWeek();
                int req = element.getRequiredEmployeesize();
                Pair<DayOfWeek, ShiftType> key = Pair.of(day, shiftTypen);

                List<Shift> shiftList = dayOfWeekAndShiftTypeToShiftListMap
                        .get(key);

                for (Shift shift : shiftList) {
                    shift.setRequiredEmployeeSize(
                            shift.getRequiredEmployeeSize() + req);

                }
            }
            List<ShiftAssignment> shiftAssignmentList = new ArrayList<>(
                    shiftList1.size());
            long shiftAssignmentId = nurseRoster.getShiftAssignmentList()
                    .get(nurseRoster.getShiftAssignmentList().size() - 1)
                    .getId() + 1L;
            for (Shift shift : shiftList1) {
                for (int i = 0; i < shift.getRequiredEmployeeSize(); i++) {
                    ShiftAssignment newShiftAssignment = new ShiftAssignment();
                    newShiftAssignment.setId(shiftAssignmentId);
                    shiftAssignmentId++;
                    newShiftAssignment.setShift(shift);
                    newShiftAssignment.setIndexInShift(i);
                    shiftAssignmentList.add(newShiftAssignment);
                    nurseRoster.getShiftAssignmentList()
                            .add(newShiftAssignment);
                    scoreDirector.afterEntityAdded(newShiftAssignment);

                }

            }

            // This should move the planning window

            nurseRosterParametrization
                    .setFirstShiftDate(newshiftdateList.get(0));
            nurseRosterParametrization.setLastShiftDate(
                    newshiftdateList.get(newshiftdateList.size() - 1));
            nurseRosterParametrization
                    .setPlanningWindowStart(newshiftdateList.get(0));
            nurseRoster
                    .setNurseRosterParametrization(nurseRosterParametrization);
            scoreDirector
                    .afterProblemPropertyChanged(nurseRosterParametrization);
        //  scoreDirector.triggerVariableListeners();

        }, true);
    }



    private void addShiftToDayOfWeekAndShiftTypeToShiftListMap(ShiftDate shiftDate, ShiftType shiftType, Shift shift) {
        Pair<DayOfWeek, ShiftType> key = Pair.of(shiftDate.getDayOfWeek(), shiftType);
        List<Shift> dayOfWeekAndShiftTypeToShiftList = dayOfWeekAndShiftTypeToShiftListMap.computeIfAbsent(key,
                k -> new ArrayList<>((shiftDateMap.size() + 6) / 7));
        dayOfWeekAndShiftTypeToShiftList.add(shift);
    }

下面是一个带有完全断言的小调试摘要,没有显示任何错误 步骤(122),花费的时间(102920),得分(0hard / 1342soft),新的最高得分(0hard / 1342soft),接受/选择的移动计数(800/884),选择的移动(2019-07-20 / E {Reece班福德} <-> 2019-07-20 / D {David Hemmings})。 17:53:37.746 [l-3-thread-2]调试LS步骤(123),花费的时间(103652),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 874),选择了动作([[2019-07-23 / D,2019-07-24 / E,2019-07-25 / E] {?-> Alana Gill},[2019-07-23 / E,2019 -07-24 / E,2019-07-25 / E,2019-07-26 / E,2019-07-27 / D,2019-07-28 / E] {?-> David Hemmings}]。 17:53:38.513 [l-3-thread-2]调试LS步骤(124),花费的时间(104419),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 887),选择了举动([[2019-07-15 / N] {?-> Sophie Dreves},[2019-07-15 / N] {?-> Reece Bamford}])。 17:53:39.337 [l-3-thread-2]调试LS步骤(125),花费的时间(105243),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 925),然后选择移动(2019-07-22 / E {Anthony Phan} <-> 2019-07-22 / D {Michael C})。 17:53:40.121 [l-3-thread-2]调试LS步骤(126),花费的时间(106027),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 943),采取了行动(2019-07-15 / L {David Hemmings-> Clayton Fletcher})。 17:53:40.972 [l-3-thread-2]调试LS步骤(127),花费的时间(106878),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 932),选择了举动(2019-07-22 / E {Sophie Dreves} <-> 2019-07-22 / L {Karen Ahrens})。 17:53:41.815 [l-3-thread-2]调试LS步骤(128),花费的时间(107721),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 932),已选择移动([[2019-07-21 / E,2019-07-22 / E,2019-07-23 / D,2019-07-24 / L,2019-07-25 / D,2019- 07-26 / E] {?-> Michael C},[2019-07-21 / D,2019-07-22 / E,2019-07-23 / E,2019-07-24 / L,2019-07 -25 / L,2019-07-26 / N] {?-> Karen Ahrens}])。 17:53:42.635 [l-3-thread-2]调试LS步骤(129),花费的时间(108541),得分(0hard / 1342soft),最佳得分(0hard / 1342soft),接受/选择的移动计数(800 / 950),选择了动作([[2019-07-19 / D,2019-07-20 / E,2019-07-21 / L] {?-> Gemma Nevin},[2019-07-19 / D,2019 -07-20 / L] {?-> David Hemmings}])。 17:53:43.481 [l-3-thread-2]调试LS步骤(130),花费的时间(109387),得分(0hard / 1343soft),新的最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 950),已选择的举动([[2019-07-15 / D,2019-07-16 / E,2019-07-17 / E,2019-07-18 / E,2019-07-19 / E] { ?-> David Hemmings},[2019-07-16 / N] {?-> Isabella},[2019-07-19 / D,2019-07-20 / L] {?-> Isabella}])。 17:53:44.290 [l-3-thread-2]调试LS步骤(131),花费的时间(110196),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 944),选择了举动(2019-07-28 / E {David Hemmings} <-> 2019-07-28 / L {Anthony Phan})。 17:53:45.053 [l-3-thread-2]调试LS步骤(132),花费的时间(110959),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 919),选择了动作([[2019-07-15 / L,2019-07-16 / L,2019-07-17 / N] {?-> Lisa Coull},[2019-07-15 / L,2019 -07-16 / L,2019-07-17 / N] {?-> Clayton Fletcher}])。 17:53:45.857 [l-3-thread-2]调试LS步骤(133),花费的时间(111763),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 936),选择了移动(2019-07-19 / N {Anthony Phan} <-> 2019-07-19 / N {Sophie Dreves})。 17:53:46.638 [l-3-thread-2]调试LS步骤(134),花费的时间(112544),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 952),选择了移动(2019-07-23 / E {David Hemmings} <-> 2019-07-23 / D {Alana Gill})。 17:53:47.437 [l-3-thread-2]调试LS步骤(135),花费的时间(113343),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 926),选择了招式([[2019-07-15 / N] {?-> Sophie Dreves},[2019-07-15 / N] {?-> Reece Bamford}])。 17:53:48.253 [l-3-thread-2]调试LS步骤(136),花费的时间(114159),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 963),选择了举动([[2019-07-27 / E,2019-07-28 / E] {?-> Isabella},[2019-07-27 / N,2019-07-28 / N] {? -> Sophie Dreves}]。 17:53:49.035 [l-3-thread-2]调试LS步骤(137),花费的时间(114941),得分(0hard / 1343soft),最佳得分(0hard / 1343soft),接受/选择的移动计数(800 / 964),选择了举动(2019-07-17 / N {Lisa Coull} <-> 2019-07-17 / N {Clayton Fletcher})。

0 个答案:

没有答案