public List<Move> createMoveList(NurseRoster nurseRoster) { List<Employee> employeeList = nurseRoster.getEmployeeList(); // This code assumes the shiftAssignmentList is sorted // Filter out every immovable ShiftAssignment List<ShiftAssignment> shiftAssignmentList = new ArrayList<ShiftAssignment>(nurseRoster.getShiftAssignmentList()); for (Iterator<ShiftAssignment> it = shiftAssignmentList.iterator(); it.hasNext(); ) { ShiftAssignment shiftAssignment = it.next(); if (!filter.accept(nurseRoster, shiftAssignment)) { it.remove(); } } // Hash the assignments per employee Map<Employee, List<AssignmentSequence>> employeeToAssignmentSequenceListMap = new HashMap<Employee, List<AssignmentSequence>>(employeeList.size()); int assignmentSequenceCapacity = nurseRoster.getShiftDateList().size() + 1 / 2; for (Employee employee : employeeList) { employeeToAssignmentSequenceListMap.put( employee, new ArrayList<AssignmentSequence>(assignmentSequenceCapacity)); } for (ShiftAssignment shiftAssignment : shiftAssignmentList) { Employee employee = shiftAssignment.getEmployee(); List<AssignmentSequence> assignmentSequenceList = employeeToAssignmentSequenceListMap.get(employee); if (assignmentSequenceList.isEmpty()) { AssignmentSequence assignmentSequence = new AssignmentSequence(shiftAssignment); assignmentSequenceList.add(assignmentSequence); } else { AssignmentSequence lastAssignmentSequence = assignmentSequenceList // getLast() .get(assignmentSequenceList.size() - 1); if (lastAssignmentSequence.belongsHere(shiftAssignment)) { lastAssignmentSequence.add(shiftAssignment); } else { AssignmentSequence assignmentSequence = new AssignmentSequence(shiftAssignment); assignmentSequenceList.add(assignmentSequence); } } } // The create the move list List<Move> moveList = new ArrayList<Move>(); // For every 2 distinct employees for (ListIterator<Employee> leftEmployeeIt = employeeList.listIterator(); leftEmployeeIt.hasNext(); ) { Employee leftEmployee = leftEmployeeIt.next(); List<AssignmentSequence> leftAssignmentSequenceList = employeeToAssignmentSequenceListMap.get(leftEmployee); for (ListIterator<Employee> rightEmployeeIt = employeeList.listIterator(leftEmployeeIt.nextIndex()); rightEmployeeIt.hasNext(); ) { Employee rightEmployee = rightEmployeeIt.next(); List<AssignmentSequence> rightAssignmentSequenceList = employeeToAssignmentSequenceListMap.get(rightEmployee); final int SWITCH_LENGTH = 3; for (AssignmentSequence leftAssignmentSequence : leftAssignmentSequenceList) { List<ShiftAssignment> leftShiftAssignmentList = leftAssignmentSequence.getShiftAssignmentList(); for (int leftIndex = 0; leftIndex <= leftShiftAssignmentList.size() - SWITCH_LENGTH; leftIndex++) { for (AssignmentSequence rightAssignmentSequence : rightAssignmentSequenceList) { List<ShiftAssignment> rightShiftAssignmentList = rightAssignmentSequence.getShiftAssignmentList(); for (int rightIndex = 0; rightIndex <= rightShiftAssignmentList.size() - SWITCH_LENGTH; rightIndex++) { List<Move> subMoveList = new ArrayList<Move>(SWITCH_LENGTH * 2); for (ShiftAssignment leftShiftAssignment : leftShiftAssignmentList.subList(leftIndex, leftIndex + SWITCH_LENGTH)) { subMoveList.add(new EmployeeChangeMove(leftShiftAssignment, rightEmployee)); } for (ShiftAssignment rightShiftAssignment : rightShiftAssignmentList.subList(rightIndex, rightIndex + SWITCH_LENGTH)) { subMoveList.add(new EmployeeChangeMove(rightShiftAssignment, leftEmployee)); } moveList.add(CompositeMove.buildMove(subMoveList)); } } } } } } return moveList; }
public List<Move> createMoveList(Solution solution) { NurseRoster nurseRoster = (NurseRoster) solution; List<Employee> employeeList = nurseRoster.getEmployeeList(); // This code assumes the shiftAssignmentList is sorted List<ShiftAssignment> shiftAssignmentList = nurseRoster.getShiftAssignmentList(); // Hash the assignments per employee Map<Employee, List<AssignmentSequence>> employeeToAssignmentSequenceListMap = new HashMap<Employee, List<AssignmentSequence>>(employeeList.size()); int assignmentSequenceCapacity = nurseRoster.getShiftDateList().size() + 1 / 2; for (Employee employee : employeeList) { employeeToAssignmentSequenceListMap.put( employee, new ArrayList<AssignmentSequence>(assignmentSequenceCapacity)); } for (ShiftAssignment shiftAssignment : shiftAssignmentList) { Employee employee = shiftAssignment.getEmployee(); List<AssignmentSequence> assignmentSequenceList = employeeToAssignmentSequenceListMap.get(employee); if (assignmentSequenceList.isEmpty()) { AssignmentSequence assignmentSequence = new AssignmentSequence(employee, shiftAssignment); assignmentSequenceList.add(assignmentSequence); } else { AssignmentSequence lastAssignmentSequence = assignmentSequenceList // getLast() .get(assignmentSequenceList.size() - 1); if (lastAssignmentSequence.belongsHere(shiftAssignment)) { lastAssignmentSequence.add(shiftAssignment); } else { AssignmentSequence assignmentSequence = new AssignmentSequence(employee, shiftAssignment); assignmentSequenceList.add(assignmentSequence); } } } // The create the move list List<Move> moveList = new ArrayList<Move>(); // For every 2 distinct employees for (ListIterator<Employee> leftEmployeeIt = employeeList.listIterator(); leftEmployeeIt.hasNext(); ) { Employee leftEmployee = leftEmployeeIt.next(); List<AssignmentSequence> leftAssignmentSequenceList = employeeToAssignmentSequenceListMap.get(leftEmployee); for (ListIterator<Employee> rightEmployeeIt = employeeList.listIterator(leftEmployeeIt.nextIndex()); rightEmployeeIt.hasNext(); ) { Employee rightEmployee = rightEmployeeIt.next(); List<AssignmentSequence> rightAssignmentSequenceList = employeeToAssignmentSequenceListMap.get(rightEmployee); LowestDayIndexAssignmentSequenceIterator lowestIt = new LowestDayIndexAssignmentSequenceIterator( leftAssignmentSequenceList, rightAssignmentSequenceList); // For every pillar part duo while (lowestIt.hasNext()) { AssignmentSequence pillarPartAssignmentSequence = lowestIt.next(); // Note: the initialCapacity is probably to high, // which is bad for memory, but the opposite is bad for performance (which is worse) List<Move> moveListByPillarPartDuo = new ArrayList<Move>( leftAssignmentSequenceList.size() + rightAssignmentSequenceList.size()); int lastDayIndex = pillarPartAssignmentSequence.getLastDayIndex(); Employee otherEmployee; int leftMinimumFirstDayIndex = Integer.MIN_VALUE; int rightMinimumFirstDayIndex = Integer.MIN_VALUE; if (lowestIt.isLastNextWasLeft()) { otherEmployee = rightEmployee; leftMinimumFirstDayIndex = lastDayIndex; } else { otherEmployee = leftEmployee; rightMinimumFirstDayIndex = lastDayIndex; } moveListByPillarPartDuo.add( new EmployeeMultipleChangeMove( pillarPartAssignmentSequence.getEmployee(), pillarPartAssignmentSequence.getShiftAssignmentList(), otherEmployee)); // For every AssignmentSequence in that pillar part duo while (lowestIt.hasNextWithMaximumFirstDayIndexes( leftMinimumFirstDayIndex, rightMinimumFirstDayIndex)) { pillarPartAssignmentSequence = lowestIt.next(); lastDayIndex = pillarPartAssignmentSequence.getLastDayIndex(); if (lowestIt.isLastNextWasLeft()) { otherEmployee = rightEmployee; leftMinimumFirstDayIndex = Math.max(leftMinimumFirstDayIndex, lastDayIndex); } else { otherEmployee = leftEmployee; rightMinimumFirstDayIndex = Math.max(rightMinimumFirstDayIndex, lastDayIndex); } moveListByPillarPartDuo.add( new EmployeeMultipleChangeMove( pillarPartAssignmentSequence.getEmployee(), pillarPartAssignmentSequence.getShiftAssignmentList(), otherEmployee)); } moveList.add(new CompositeMove(moveListByPillarPartDuo)); } } } return moveList; }