From f555fa7514ba0ea4eed1d9eae5a7e3f960215a8a Mon Sep 17 00:00:00 2001 From: tomas-muller Date: Sun, 15 Nov 2020 12:59:47 +0100 Subject: [PATCH] Student Scheduling: Failed Neighbour Assignment - backtrack and student swap now also listen for failed neibhours, putting the failed student/request back into the queue - improving success of each phase, especially when there are higher number of solver threads - also students are put at the beginning of the queue, ensuring that priority students are processed first --- .../StudentSctNeighbourSelection.java | 12 ++++++-- .../selection/BacktrackSelection.java | 29 ++++++++++++++++-- .../selection/BranchBoundSelection.java | 21 ++++++++++++- .../selection/SwapStudentSelection.java | 30 +++++++++++++++---- 4 files changed, 81 insertions(+), 11 deletions(-) diff --git a/src/org/cpsolver/studentsct/heuristics/StudentSctNeighbourSelection.java b/src/org/cpsolver/studentsct/heuristics/StudentSctNeighbourSelection.java index 44786376..eed04261 100644 --- a/src/org/cpsolver/studentsct/heuristics/StudentSctNeighbourSelection.java +++ b/src/org/cpsolver/studentsct/heuristics/StudentSctNeighbourSelection.java @@ -1,5 +1,7 @@ package org.cpsolver.studentsct.heuristics; +import java.util.Iterator; + import org.cpsolver.ifs.assignment.Assignment; import org.cpsolver.ifs.heuristics.NeighbourSelection; import org.cpsolver.ifs.heuristics.RoundRobinNeighbourSelection; @@ -112,6 +114,11 @@ public void init(Solver solver) { super.init(solver); setup(solver); solver.setUpdateProgress(false); + for (Iterator> i = solver.getSolverListeners().iterator(); i.hasNext(); ) { + SolverListener listener = i.next(); + if (listener instanceof StudentSctNeighbourSelection) + i.remove(); + } solver.addSolverListener(this); } @@ -264,10 +271,11 @@ public boolean neighbourSelected(Assignment assignment, lon return true; } + @SuppressWarnings("unchecked") @Override public void neighbourFailed(Assignment assignment, long iteration, Neighbour neighbour) { NeighbourSelection selection = getSelection(); - if (neighbour instanceof BranchBoundSelection.BranchBoundNeighbour && selection instanceof BranchBoundSelection) - ((BranchBoundSelection)selection).addStudent(((BranchBoundSelection.BranchBoundNeighbour)neighbour).getStudent()); + if (selection instanceof SolverListener) + ((SolverListener)selection).neighbourFailed(assignment, iteration, neighbour); } } diff --git a/src/org/cpsolver/studentsct/heuristics/selection/BacktrackSelection.java b/src/org/cpsolver/studentsct/heuristics/selection/BacktrackSelection.java index fe4a7910..0940626a 100644 --- a/src/org/cpsolver/studentsct/heuristics/selection/BacktrackSelection.java +++ b/src/org/cpsolver/studentsct/heuristics/selection/BacktrackSelection.java @@ -7,14 +7,15 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Queue; import org.cpsolver.ifs.assignment.Assignment; +import org.cpsolver.ifs.heuristics.BacktrackNeighbourSelection; import org.cpsolver.ifs.heuristics.NeighbourSelection; import org.cpsolver.ifs.model.InfoProvider; import org.cpsolver.ifs.model.Neighbour; import org.cpsolver.ifs.solution.Solution; import org.cpsolver.ifs.solver.Solver; +import org.cpsolver.ifs.solver.SolverListener; import org.cpsolver.ifs.util.DataProperties; import org.cpsolver.ifs.util.Progress; import org.cpsolver.studentsct.filter.StudentFilter; @@ -52,10 +53,10 @@ * http://www.gnu.org/licenses/. */ -public class BacktrackSelection implements NeighbourSelection, InfoProvider { +public class BacktrackSelection implements NeighbourSelection, InfoProvider, SolverListener { private static DecimalFormat sDF = new DecimalFormat("0.00"); protected RandomizedBacktrackNeighbourSelection iRBtNSel = null; - protected Queue iRequests = null; + protected LinkedList iRequests = null; protected boolean iIncludeAssignedRequests = false; protected long iNbrIterations = 0; @@ -100,6 +101,10 @@ protected synchronized Request nextRequest() { if (iFilter == null || iFilter.accept(request.getStudent())) return request; } } + + public synchronized void addRequest(Request request) { + if (iRequests != null && request != null && !request.getStudent().isDummy()) iRequests.addFirst(request); + } @Override public Neighbour selectNeighbour(Solution solution) { @@ -144,4 +149,22 @@ public void getInfo(Assignment assignment, Map assignment, long iteration, Request variable) { + return false; + } + @Override + public boolean valueSelected(Assignment assignment, long iteration, Request variable, Enrollment value) { + return false; + } + @Override + public boolean neighbourSelected(Assignment assignment, long iteration, Neighbour neighbour) { + return false; + } + @Override + public void neighbourFailed(Assignment assignment, long iteration, Neighbour neighbour) { + if (neighbour instanceof BacktrackNeighbourSelection.BackTrackNeighbour) + addRequest(((BacktrackNeighbourSelection.BackTrackNeighbour)neighbour).getAssignments().get(0).getRequest()); + } } diff --git a/src/org/cpsolver/studentsct/heuristics/selection/BranchBoundSelection.java b/src/org/cpsolver/studentsct/heuristics/selection/BranchBoundSelection.java index 9d1fd598..4a171fc8 100644 --- a/src/org/cpsolver/studentsct/heuristics/selection/BranchBoundSelection.java +++ b/src/org/cpsolver/studentsct/heuristics/selection/BranchBoundSelection.java @@ -21,6 +21,7 @@ import org.cpsolver.ifs.model.Neighbour; import org.cpsolver.ifs.solution.Solution; import org.cpsolver.ifs.solver.Solver; +import org.cpsolver.ifs.solver.SolverListener; import org.cpsolver.ifs.util.DataProperties; import org.cpsolver.ifs.util.JProf; import org.cpsolver.ifs.util.Progress; @@ -95,7 +96,7 @@ * http://www.gnu.org/licenses/. */ -public class BranchBoundSelection implements NeighbourSelection, InfoProvider { +public class BranchBoundSelection implements NeighbourSelection, InfoProvider, SolverListener { private static Logger sLog = Logger.getLogger(BranchBoundSelection.class); private static DecimalFormat sDF = new DecimalFormat("0.00"); protected int iTimeout = 10000; @@ -958,4 +959,22 @@ public void getInfo(Assignment assignment, Map assignment, long iteration, Request variable) { + return false; + } + @Override + public boolean valueSelected(Assignment assignment, long iteration, Request variable, Enrollment value) { + return false; + } + @Override + public boolean neighbourSelected(Assignment assignment, long iteration, Neighbour neighbour) { + return false; + } + @Override + public void neighbourFailed(Assignment assignment, long iteration, Neighbour neighbour) { + if (neighbour instanceof BranchBoundNeighbour) + addStudent(((BranchBoundNeighbour)neighbour).getStudent()); + } } diff --git a/src/org/cpsolver/studentsct/heuristics/selection/SwapStudentSelection.java b/src/org/cpsolver/studentsct/heuristics/selection/SwapStudentSelection.java index 56734742..c78d4425 100644 --- a/src/org/cpsolver/studentsct/heuristics/selection/SwapStudentSelection.java +++ b/src/org/cpsolver/studentsct/heuristics/selection/SwapStudentSelection.java @@ -9,7 +9,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Set; @@ -20,6 +19,7 @@ import org.cpsolver.ifs.model.Neighbour; import org.cpsolver.ifs.solution.Solution; import org.cpsolver.ifs.solver.Solver; +import org.cpsolver.ifs.solver.SolverListener; import org.cpsolver.ifs.util.DataProperties; import org.cpsolver.ifs.util.JProf; import org.cpsolver.ifs.util.Progress; @@ -92,10 +92,10 @@ * http://www.gnu.org/licenses/. */ -public class SwapStudentSelection implements NeighbourSelection, ProblemStudentsProvider, InfoProvider { +public class SwapStudentSelection implements NeighbourSelection, ProblemStudentsProvider, InfoProvider, SolverListener { private static Logger sLog = Logger.getLogger(SwapStudentSelection.class); private Set iProblemStudents = Collections.synchronizedSet(new HashSet()); - private Queue iStudents = null; + private LinkedList iStudents = null; private static DecimalFormat sDF = new DecimalFormat("0.00"); private int iTimeout = 5000; private int iMaxValues = 100; @@ -146,8 +146,8 @@ protected synchronized Student nextStudent() { return iStudents.poll(); } - protected synchronized void addStudent(Student student) { - if (iStudents != null && !student.isDummy()) iStudents.add(student); + public synchronized void addStudent(Student student) { + if (iStudents != null && !student.isDummy()) iStudents.addFirst(student); } /** @@ -459,6 +459,8 @@ public SwapStudentNeighbour(double value, Enrollment enrollment, List assignment) { return iValue; } + + public Student getStudent() { return iEnrollment.getStudent(); } /** * Perform the move. All the requeired swaps are identified and @@ -513,4 +515,22 @@ public void getInfo(Assignment assignment, Map assignment, Map info, Collection variables) { } + + @Override + public boolean variableSelected(Assignment assignment, long iteration, Request variable) { + return false; + } + @Override + public boolean valueSelected(Assignment assignment, long iteration, Request variable, Enrollment value) { + return false; + } + @Override + public boolean neighbourSelected(Assignment assignment, long iteration, Neighbour neighbour) { + return false; + } + @Override + public void neighbourFailed(Assignment assignment, long iteration, Neighbour neighbour) { + if (neighbour instanceof SwapStudentNeighbour) + addStudent(((SwapStudentNeighbour)neighbour).getStudent()); + } }