[jboss-svn-commits] JBL Code SVN: r33462 - in labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move: factory and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Sat Jun 12 03:49:32 EDT 2010
Author: ge0ffrey
Date: 2010-06-12 03:49:31 -0400 (Sat, 12 Jun 2010)
New Revision: 33462
Added:
labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/EmployeeMultipleChangeMove.java
labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentPillarPartSwitchMoveFactory.java
Modified:
labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength2MoveFactory.java
labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength3MoveFactory.java
Log:
fix forgetting to add bug + a pillar part implementation
Copied: labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/EmployeeMultipleChangeMove.java (from rev 33335, labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/EmployeeChangeMove.java)
===================================================================
--- labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/EmployeeMultipleChangeMove.java (rev 0)
+++ labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/EmployeeMultipleChangeMove.java 2010-06-12 07:49:31 UTC (rev 33462)
@@ -0,0 +1,80 @@
+package org.drools.planner.examples.nurserostering.solver.move;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.drools.WorkingMemory;
+import org.drools.planner.core.localsearch.decider.acceptor.tabu.TabuPropertyEnabled;
+import org.drools.planner.core.move.Move;
+import org.drools.planner.examples.nurserostering.domain.Assignment;
+import org.drools.planner.examples.nurserostering.domain.Employee;
+
+/**
+ * @author Geoffrey De Smet
+ */
+public class EmployeeMultipleChangeMove implements Move, TabuPropertyEnabled {
+
+ private Employee fromEmployee;
+ private List<Assignment> assignmentList;
+ private Employee toEmployee;
+
+ public EmployeeMultipleChangeMove(Employee fromEmployee, List<Assignment> assignmentList, Employee toEmployee) {
+ this.fromEmployee = fromEmployee;
+ this.assignmentList = assignmentList;
+ this.toEmployee = toEmployee;
+ }
+
+ public boolean isMoveDoable(WorkingMemory workingMemory) {
+ return !ObjectUtils.equals(fromEmployee, toEmployee);
+ }
+
+ public Move createUndoMove(WorkingMemory workingMemory) {
+ return new EmployeeMultipleChangeMove(toEmployee, assignmentList, fromEmployee);
+ }
+
+ public void doMove(WorkingMemory workingMemory) {
+ for (Assignment assignment : assignmentList) {
+ if (!assignment.getEmployee().equals(fromEmployee)) {
+ throw new IllegalStateException("The assignment (" + assignment + ") should have the same employee ("
+ + fromEmployee + ") as the fromEmployee (" + fromEmployee + ").");
+ }
+ NurseRosterMoveHelper.moveEmployee(workingMemory, assignment, toEmployee);
+ }
+ }
+
+ public Collection<? extends Object> getTabuProperties() {
+ return Collections.singletonList(assignmentList);
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ } else if (o instanceof EmployeeMultipleChangeMove) {
+ EmployeeMultipleChangeMove other = (EmployeeMultipleChangeMove) o;
+ return new EqualsBuilder()
+ .append(fromEmployee, other.fromEmployee)
+ .append(assignmentList, other.assignmentList)
+ .append(toEmployee, other.toEmployee)
+ .isEquals();
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(fromEmployee)
+ .append(assignmentList)
+ .append(toEmployee)
+ .toHashCode();
+ }
+
+ public String toString() {
+ return assignmentList + " => " + toEmployee;
+ }
+
+}
Added: labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentPillarPartSwitchMoveFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentPillarPartSwitchMoveFactory.java (rev 0)
+++ labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentPillarPartSwitchMoveFactory.java 2010-06-12 07:49:31 UTC (rev 33462)
@@ -0,0 +1,275 @@
+package org.drools.planner.examples.nurserostering.solver.move.factory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import org.drools.planner.core.move.CompositeMove;
+import org.drools.planner.core.move.Move;
+import org.drools.planner.core.move.factory.AbstractMoveFactory;
+import org.drools.planner.core.solution.Solution;
+import org.drools.planner.examples.nurserostering.domain.Assignment;
+import org.drools.planner.examples.nurserostering.domain.Employee;
+import org.drools.planner.examples.nurserostering.domain.NurseRoster;
+import org.drools.planner.examples.nurserostering.domain.solver.EmployeeWorkSequence;
+import org.drools.planner.examples.nurserostering.solver.move.EmployeeMultipleChangeMove;
+
+/**
+ * @author Geoffrey De Smet
+ */
+public class AssignmentPillarPartSwitchMoveFactory extends AbstractMoveFactory {
+
+ public List<Move> createMoveList(Solution solution) {
+ NurseRoster nurseRoster = (NurseRoster) solution;
+ List<Employee> employeeList = nurseRoster.getEmployeeList();
+ // This code assumes the assignmentList is sorted
+ List<Assignment> assignmentList = nurseRoster.getAssignmentList();
+
+ // 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 (Assignment assignment : assignmentList) {
+ Employee employee = assignment.getEmployee();
+ List<AssignmentSequence> assignmentSequenceList = employeeToAssignmentSequenceListMap.get(employee);
+ if (assignmentSequenceList.isEmpty()) {
+ AssignmentSequence assignmentSequence = new AssignmentSequence(employee, assignment);
+ assignmentSequenceList.add(assignmentSequence);
+ } else {
+ AssignmentSequence lastAssignmentSequence = assignmentSequenceList // getLast()
+ .get(assignmentSequenceList.size() - 1);
+ if (lastAssignmentSequence.belongsHere(assignment)) {
+ lastAssignmentSequence.add(assignment);
+ } else {
+ AssignmentSequence assignmentSequence = new AssignmentSequence(employee, assignment);
+ 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.getAssignmentList(),
+ 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.getAssignmentList(),
+ otherEmployee));
+ }
+ moveList.add(new CompositeMove(moveListByPillarPartDuo));
+ }
+ }
+ }
+ return moveList;
+ }
+
+ /**
+ * TODO DRY with {@link EmployeeWorkSequence}
+ */
+ private static class AssignmentSequence {
+
+ private Employee employee;
+ private List<Assignment> assignmentList;
+ private int firstDayIndex;
+ private int lastDayIndex;
+
+ private AssignmentSequence(Employee employee, Assignment assignment) {
+ this.employee = employee;
+ assignmentList = new ArrayList<Assignment>();
+ assignmentList.add(assignment);
+ firstDayIndex = assignment.getShiftDateDayIndex();
+ lastDayIndex = firstDayIndex;
+ }
+
+ public Employee getEmployee() {
+ return employee;
+ }
+
+ public List<Assignment> getAssignmentList() {
+ return assignmentList;
+ }
+
+ public int getFirstDayIndex() {
+ return firstDayIndex;
+ }
+
+ public int getLastDayIndex() {
+ return lastDayIndex;
+ }
+
+ private void add(Assignment assignment) {
+ assignmentList.add(assignment);
+ int dayIndex = assignment.getShiftDateDayIndex();
+ if (dayIndex < lastDayIndex) {
+ throw new IllegalStateException("The assignmentList is expected to be sorted by shiftDate.");
+ }
+ lastDayIndex = dayIndex;
+ }
+
+ private boolean belongsHere(Assignment assignment) {
+ return assignment.getShiftDateDayIndex() <= (lastDayIndex + 1);
+ }
+
+ }
+
+ private class LowestDayIndexAssignmentSequenceIterator implements Iterator<AssignmentSequence> {
+
+ private Iterator<AssignmentSequence> leftIterator;
+ private Iterator<AssignmentSequence> rightIterator;
+
+ private boolean leftHasNext = true;
+ private boolean rightHasNext = true;
+
+ private AssignmentSequence nextLeft;
+ private AssignmentSequence nextRight;
+
+ private boolean lastNextWasLeft;
+
+ public LowestDayIndexAssignmentSequenceIterator(
+ List<AssignmentSequence> leftAssignmentList, List<AssignmentSequence> rightAssignmentList) {
+ // Buffer the nextLeft and nextRight
+ leftIterator = leftAssignmentList.iterator();
+ if (leftIterator.hasNext()) {
+ nextLeft = leftIterator.next();
+ } else {
+ leftHasNext = false;
+ nextLeft = null;
+ }
+ rightIterator = rightAssignmentList.iterator();
+ if (rightIterator.hasNext()) {
+ nextRight = rightIterator.next();
+ } else {
+ rightHasNext = false;
+ nextRight = null;
+ }
+ }
+
+ public boolean hasNext() {
+ return leftHasNext || rightHasNext;
+ }
+
+ public boolean hasNextWithMaximumFirstDayIndexes(
+ int leftMinimumFirstDayIndex, int rightMinimumFirstDayIndex) {
+ if (!hasNext()) {
+ return false;
+ }
+ boolean nextIsLeft = nextIsLeft();
+ if (nextIsLeft) {
+ int firstDayIndex = nextLeft.getFirstDayIndex();
+ // It should not be conflict in the same pillar and it should be in conflict with the other pillar
+ return firstDayIndex > leftMinimumFirstDayIndex && firstDayIndex <= rightMinimumFirstDayIndex;
+ } else {
+ int firstDayIndex = nextRight.getFirstDayIndex();
+ // It should not be conflict in the same pillar and it should be in conflict with the other pillar
+ return firstDayIndex > rightMinimumFirstDayIndex && firstDayIndex <= leftMinimumFirstDayIndex;
+ }
+ }
+
+ public AssignmentSequence next() {
+ lastNextWasLeft = nextIsLeft();
+ // Buffer the nextLeft or nextRight
+ AssignmentSequence lowest;
+ if (lastNextWasLeft) {
+ lowest = nextLeft;
+ if (leftIterator.hasNext()) {
+ nextLeft = leftIterator.next();
+ } else {
+ leftHasNext = false;
+ nextLeft = null;
+ }
+ } else {
+ lowest = nextRight;
+ if (rightIterator.hasNext()) {
+ nextRight = rightIterator.next();
+ } else {
+ rightHasNext = false;
+ nextRight = null;
+ }
+ }
+ return lowest;
+ }
+
+ private boolean nextIsLeft() {
+ boolean returnLeft;
+ if (leftHasNext) {
+ if (rightHasNext) {
+ int leftFirstDayIndex = nextLeft.getFirstDayIndex();
+ int rightFirstDayIndex = nextRight.getFirstDayIndex();
+ returnLeft = leftFirstDayIndex <= rightFirstDayIndex;
+ } else {
+ returnLeft = true;
+ }
+ } else {
+ if (rightHasNext) {
+ returnLeft = false;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+ return returnLeft;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("Remove not supported.");
+ }
+
+ public boolean isLastNextWasLeft() {
+ return lastNextWasLeft;
+ }
+
+ }
+
+}
Modified: labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength2MoveFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength2MoveFactory.java 2010-06-12 06:18:44 UTC (rev 33461)
+++ labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength2MoveFactory.java 2010-06-12 07:49:31 UTC (rev 33462)
@@ -108,6 +108,7 @@
private AssignmentSequence(Assignment assignment) {
assignmentList = new ArrayList<Assignment>();
+ assignmentList.add(assignment);
firstDayIndex = assignment.getShiftDateDayIndex();
lastDayIndex = firstDayIndex;
}
Modified: labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength3MoveFactory.java
===================================================================
--- labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength3MoveFactory.java 2010-06-12 06:18:44 UTC (rev 33461)
+++ labs/jbossrules/trunk/drools-planner/drools-planner-examples/src/main/java/org/drools/planner/examples/nurserostering/solver/move/factory/AssignmentSequenceSwitchLength3MoveFactory.java 2010-06-12 07:49:31 UTC (rev 33462)
@@ -105,6 +105,7 @@
private AssignmentSequence(Assignment assignment) {
assignmentList = new ArrayList<Assignment>();
+ assignmentList.add(assignment);
firstDayIndex = assignment.getShiftDateDayIndex();
lastDayIndex = firstDayIndex;
}
More information about the jboss-svn-commits
mailing list