[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