Непрерывное обновление и обновление в режиме реального времени - PullRequest
0 голосов
/ 24 июня 2019

Я не вижу корректного обновления назначений смены, хотя все остальные элементы (шаблоны) обновляются, включая запросы. Я работаю с 14-дневным списком смен для 12 сотрудников.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 Bamford} <-> 2019-07-20 / D {David Hemmings}).17: 53: 37.746 [l-3-thread-2] DEBUG LS шаг (123), потраченное время (103652), оценка (0hard / 1342soft), лучший результат (0hard / 1342soft), количество принятых / выбранных ходов (800 /874), выбранный ход ([[2019-07-23 / D, 2019-07-24 / E, 2019-07-25 / E] {? -> Алана Джилл}, [2019-07-23 / E, 2019-07-24 / E, 2019-07-25 / E, 2019-07-26 / E, 2019-07-27 / D, 2019-07-28 / E] {? -> Дэвид Хеммингс}]).17: 53: 38.513 [l-3-thread-2] DEBUG LS шаг (124), потраченное время (104419), оценка (0hard / 1342soft), лучший результат (0hard / 1342soft), количество принятых / выбранных ходов (800 /887), выбранный ход ([[2019-07-15 / N] {? -> Софи Дривс}, [2019-07-15 / N] {? -> Рис Бэмфорд}]).17: 53: 39.337 [l-3-thread-2] DEBUG LS шаг (125), затраченное время (105243), оценка (0hard / 1342soft), лучший результат (0hard / 1342soft), количество принятых / выбранных ходов (800 /925), выбранный ход (2019-07-22 / E {Энтони Фан} <-> 2019-07-22 / D {Майкл С}).17: 53: 40.121 [l-3-thread-2] DEBUG LS шаг (126), затраченное время (106027), оценка (0hard / 1342soft), лучший результат (0hard / 1342soft), количество принятых / выбранных ходов (800 /943), выбранный ход (2019-07-15 / L {Дэвид Хеммингс -> Клейтон Флетчер}).17: 53: 40.972 [l-3-thread-2] DEBUG 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] DEBUG 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] {? -> Карен Аренс}]).17: 53: 42.635 [l-3-thread-2] DEBUG LS шаг (129), потраченное время (108541), оценка (0hard / 1342soft), лучший результат (0hard / 1342soft), количество принятых / выбранных ходов (800 /950), выбранный ход ([[2019-07-19 / D, 2019-07-20 / E, 2019-07-21 / L] {? -> Джемма Невин}, [2019-07-19 / D, 2019-07-20 / L] {? -> Дэвид Хеммингс}]).17: 53: 43.481 [l-3-thread-2] DEBUG 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] {? -> Дэвид Хеммингс}, [2019-07-16 / N] {? -> Изабелла}, [2019-07-19 / D, 2019-07-20 / L] {? -> Изабелла}]).17: 53: 44.290 [l-3-thread-2] DEBUG LS шаг (131), потраченное время (110196), оценка (0hard / 1343soft), лучший результат (0hard / 1343soft), количество принятых / выбранных ходов (800 /944), выбранный ход (2019-07-28 / E {Дэвид Хеммингс} <-> 2019-07-28 / L {Энтони Фан}).17: 53: 45.053 [l-3-thread-2] DEBUG 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] DEBUG LS шаг (133), затраченное время (111763), счет (0hard / 1343soft), лучший результат (0hard / 1343soft), количество принятых / выбранных ходов (800 /936), выбранный ход (2019-07-19 / N {Энтони Фан} <-> 2019-07-19 / N {Софи Дривс}).17: 53: 46.638 [l-3-thread-2] DEBUG 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] DEBUG LS шаг (135), потраченное время (113343), оценка (0hard / 1343soft), лучший результат (0hard / 1343soft), количество принятых / выбранных ходов (800 /926), выбранный ход ([[2019-07-15 / N] {? -> Софи Дривс}, [2019-07-15 / N] {? -> Рис Бэмфорд}]).17: 53: 48.253 [l-3-thread-2] DEBUG LS шаг (136), затраченное время (114159), оценка (0hard / 1343soft), лучший результат (0hard / 1343soft), количество принятых / выбранных ходов (800 /963), выбранный ход ([[2019-07-27 / E, 2019-07-28 / E] {? -> Изабелла}, [2019-07-27 / N, 2019-07-28 / N] {?-> Софи Древес}]).17: 53: 49.035 [l-3-thread-2] DEBUG LS шаг (137), затраченное время (114941), счет (0hard / 1343soft), лучший результат (0hard / 1343soft), количество принятых / выбранных ходов (800 /964), выбранный ход (2019-07-17 / N {Lisa Coull} <-> 2019-07-17 / N {Клейтон Флетчер}).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...