Skip to content

Commit

Permalink
Student Scheduling: Failed Neighbour Assignment
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
tomas-muller committed Nov 15, 2020
1 parent 1639c6f commit f555fa7
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 11 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -112,6 +114,11 @@ public void init(Solver<Request, Enrollment> solver) {
super.init(solver);
setup(solver);
solver.setUpdateProgress(false);
for (Iterator<SolverListener<Request, Enrollment>> i = solver.getSolverListeners().iterator(); i.hasNext(); ) {
SolverListener<Request, Enrollment> listener = i.next();
if (listener instanceof StudentSctNeighbourSelection)
i.remove();
}
solver.addSolverListener(this);
}

Expand Down Expand Up @@ -264,10 +271,11 @@ public boolean neighbourSelected(Assignment<Request, Enrollment> assignment, lon
return true;
}

@SuppressWarnings("unchecked")
@Override
public void neighbourFailed(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
NeighbourSelection<Request, Enrollment> selection = getSelection();
if (neighbour instanceof BranchBoundSelection.BranchBoundNeighbour && selection instanceof BranchBoundSelection)
((BranchBoundSelection)selection).addStudent(((BranchBoundSelection.BranchBoundNeighbour)neighbour).getStudent());
if (selection instanceof SolverListener)
((SolverListener<Request, Enrollment>)selection).neighbourFailed(assignment, iteration, neighbour);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -52,10 +53,10 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/

public class BacktrackSelection implements NeighbourSelection<Request, Enrollment>, InfoProvider<Request, Enrollment> {
public class BacktrackSelection implements NeighbourSelection<Request, Enrollment>, InfoProvider<Request, Enrollment>, SolverListener<Request, Enrollment> {
private static DecimalFormat sDF = new DecimalFormat("0.00");
protected RandomizedBacktrackNeighbourSelection iRBtNSel = null;
protected Queue<Request> iRequests = null;
protected LinkedList<Request> iRequests = null;
protected boolean iIncludeAssignedRequests = false;

protected long iNbrIterations = 0;
Expand Down Expand Up @@ -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<Request, Enrollment> selectNeighbour(Solution<Request, Enrollment> solution) {
Expand Down Expand Up @@ -144,4 +149,22 @@ public void getInfo(Assignment<Request, Enrollment> assignment, Map<String, Stri
* Only consider students meeting the given filter.
*/
public BacktrackSelection withFilter(StudentFilter filter) { iFilter = filter; return this; }

@Override
public boolean variableSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable) {
return false;
}
@Override
public boolean valueSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable, Enrollment value) {
return false;
}
@Override
public boolean neighbourSelected(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
return false;
}
@Override
public void neighbourFailed(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
if (neighbour instanceof BacktrackNeighbourSelection.BackTrackNeighbour)
addRequest(((BacktrackNeighbourSelection<Request, Enrollment>.BackTrackNeighbour)neighbour).getAssignments().get(0).getRequest());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -95,7 +96,7 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/

public class BranchBoundSelection implements NeighbourSelection<Request, Enrollment>, InfoProvider<Request, Enrollment> {
public class BranchBoundSelection implements NeighbourSelection<Request, Enrollment>, InfoProvider<Request, Enrollment>, SolverListener<Request, Enrollment> {
private static Logger sLog = Logger.getLogger(BranchBoundSelection.class);
private static DecimalFormat sDF = new DecimalFormat("0.00");
protected int iTimeout = 10000;
Expand Down Expand Up @@ -958,4 +959,22 @@ public void getInfo(Assignment<Request, Enrollment> assignment, Map<String, Stri
* Only consider students meeting the given filter.
*/
public BranchBoundSelection withFilter(StudentFilter filter) { iFilter = filter; return this; }

@Override
public boolean variableSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable) {
return false;
}
@Override
public boolean valueSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable, Enrollment value) {
return false;
}
@Override
public boolean neighbourSelected(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
return false;
}
@Override
public void neighbourFailed(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
if (neighbour instanceof BranchBoundNeighbour)
addStudent(((BranchBoundNeighbour)neighbour).getStudent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;


Expand All @@ -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;
Expand Down Expand Up @@ -92,10 +92,10 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/

public class SwapStudentSelection implements NeighbourSelection<Request, Enrollment>, ProblemStudentsProvider, InfoProvider<Request, Enrollment> {
public class SwapStudentSelection implements NeighbourSelection<Request, Enrollment>, ProblemStudentsProvider, InfoProvider<Request, Enrollment>, SolverListener<Request, Enrollment> {
private static Logger sLog = Logger.getLogger(SwapStudentSelection.class);
private Set<Student> iProblemStudents = Collections.synchronizedSet(new HashSet<Student>());
private Queue<Student> iStudents = null;
private LinkedList<Student> iStudents = null;
private static DecimalFormat sDF = new DecimalFormat("0.00");
private int iTimeout = 5000;
private int iMaxValues = 100;
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -459,6 +459,8 @@ public SwapStudentNeighbour(double value, Enrollment enrollment, List<Enrollment
public double value(Assignment<Request, Enrollment> assignment) {
return iValue;
}

public Student getStudent() { return iEnrollment.getStudent(); }

/**
* Perform the move. All the requeired swaps are identified and
Expand Down Expand Up @@ -513,4 +515,22 @@ public void getInfo(Assignment<Request, Enrollment> assignment, Map<String, Stri
@Override
public void getInfo(Assignment<Request, Enrollment> assignment, Map<String, String> info, Collection<Request> variables) {
}

@Override
public boolean variableSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable) {
return false;
}
@Override
public boolean valueSelected(Assignment<Request, Enrollment> assignment, long iteration, Request variable, Enrollment value) {
return false;
}
@Override
public boolean neighbourSelected(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
return false;
}
@Override
public void neighbourFailed(Assignment<Request, Enrollment> assignment, long iteration, Neighbour<Request, Enrollment> neighbour) {
if (neighbour instanceof SwapStudentNeighbour)
addStudent(((SwapStudentNeighbour)neighbour).getStudent());
}
}

0 comments on commit f555fa7

Please sign in to comment.