use of org.cpsolver.exam.model.ExamPlacement in project cpsolver by UniTime.
the class ExamTabuSearch method selectNeighbour.
/**
* Neighbor selection
*/
@Override
public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) {
if (iFirstIteration < 0)
iFirstIteration = solution.getIteration();
TabuList tabu = getContext(solution.getAssignment());
long idle = solution.getIteration() - Math.max(iFirstIteration, solution.getBestIteration());
if (idle > iMaxIdleIterations) {
sLog.debug(" [tabu] max idle iterations reached");
iFirstIteration = -1;
if (tabu.size() > 0)
tabu.clear();
return null;
}
if (tabu.size() > 0 && iTabuMaxSize > iTabuMinSize) {
if (idle == 0) {
tabu.resize(iTabuMinSize);
} else if (idle % (iMaxIdleIterations / (iTabuMaxSize - iTabuMinSize)) == 0) {
tabu.resize(Math.min(iTabuMaxSize, tabu.size() + 1));
}
}
boolean acceptConflicts = solution.getModel().getBestUnassignedVariables() > 0;
ExamModel model = (ExamModel) solution.getModel();
Assignment<Exam, ExamPlacement> assignment = solution.getAssignment();
double bestEval = 0.0;
List<ExamPlacement> best = null;
for (Exam exam : model.variables()) {
ExamPlacement assigned = assignment.getValue(exam);
double assignedVal = (assigned == null ? iConflictWeight : iValueWeight * assigned.toDouble(assignment));
for (ExamPeriodPlacement period : exam.getPeriodPlacements()) {
Set<ExamRoomPlacement> rooms = exam.findBestAvailableRooms(assignment, period);
if (rooms == null)
rooms = exam.findRoomsRandom(assignment, period, false);
if (rooms == null)
continue;
ExamPlacement value = new ExamPlacement(exam, period, rooms);
if (value.equals(assigned))
continue;
double eval = iValueWeight * value.toDouble(assignment) - assignedVal;
if (acceptConflicts) {
Set<ExamPlacement> conflicts = model.conflictValues(assignment, value);
for (ExamPlacement conflict : conflicts) {
eval -= iValueWeight * conflict.toDouble(assignment);
eval += iConflictWeight * (1.0 + (iStat == null ? 0.0 : iStat.countRemovals(solution.getIteration(), conflict, value)));
}
} else {
if (model.inConflict(assignment, value))
continue;
}
if (tabu.size() > 0 && tabu.contains(exam.getId() + ":" + value.getPeriod().getIndex())) {
int un = model.variables().size() - assignment.nrAssignedVariables() - (assigned == null ? 0 : 1);
if (un > model.getBestUnassignedVariables())
continue;
if (un == model.getBestUnassignedVariables() && model.getTotalValue(assignment) + eval >= solution.getBestValue())
continue;
}
if (best == null || bestEval > eval) {
if (best == null)
best = new ArrayList<ExamPlacement>();
else
best.clear();
best.add(value);
bestEval = eval;
} else if (bestEval == eval) {
best.add(value);
}
}
}
if (best == null) {
sLog.debug(" [tabu] --none--");
iFirstIteration = -1;
if (tabu.size() > 0)
tabu.clear();
return null;
}
ExamPlacement bestVal = ToolBox.random(best);
if (sLog.isDebugEnabled()) {
Set<ExamPlacement> conflicts = model.conflictValues(assignment, bestVal);
double wconf = (iStat == null ? 0.0 : iStat.countRemovals(solution.getIteration(), conflicts, bestVal));
sLog.debug(" [tabu] " + bestVal + " (" + (assignment.getValue(bestVal.variable()) == null ? "" : "was=" + assignment.getValue(bestVal.variable()) + ", ") + "val=" + bestEval + (conflicts.isEmpty() ? "" : ", conf=" + (wconf + conflicts.size()) + "/" + conflicts) + ")");
}
if (tabu.size() > 0)
tabu.add(bestVal.variable().getId() + ":" + bestVal.getPeriod().getIndex());
return new SimpleNeighbour<Exam, ExamPlacement>(bestVal.variable(), bestVal);
}
use of org.cpsolver.exam.model.ExamPlacement in project cpsolver by UniTime.
the class ExamConstruction method checkLocalOptimality.
/**
* Find a new assignment of one of the assigned exams that improves the time
* cost {@link ExamPlacement#getTimeCost(Assignment)} and for which there is a set of
* available rooms {@link Exam#findBestAvailableRooms(Assignment, ExamPeriodPlacement)}.
* Return null, if there is no such assignment (the problem is considered
* locally optimal).
* @param assignment current assignment
* @param model problem model
* @return a neighbour to assign or null if none was found
*/
public Neighbour<Exam, ExamPlacement> checkLocalOptimality(Assignment<Exam, ExamPlacement> assignment, ExamModel model) {
if (iCheckLocalOptimality) {
Context context = getContext(assignment);
for (Exam exam : assignment.assignedVariables()) {
ExamPlacement current = assignment.getValue(exam);
if (current.getTimeCost(assignment) <= 0)
continue;
ExamPlacement best = null;
for (ExamPeriodPlacement period : exam.getPeriodPlacements()) {
if (exam.countStudentConflicts(assignment, period) > 0) {
if (context.assignments().contains(exam.getId() + ":" + period.getIndex()))
continue;
}
if (!exam.checkDistributionConstraints(assignment, period))
continue;
ExamPlacement placement = new ExamPlacement(exam, period, null);
if (best == null || best.getTimeCost(assignment) > placement.getTimeCost(assignment)) {
Set<ExamRoomPlacement> rooms = exam.findBestAvailableRooms(assignment, period);
if (rooms != null)
best = new ExamPlacement(exam, period, rooms);
}
}
if (best != null && best.getTimeCost(assignment) < current.getTimeCost(assignment))
return new ExamSimpleNeighbour(assignment, best);
}
}
iActive = false;
return null;
}
use of org.cpsolver.exam.model.ExamPlacement in project cpsolver by UniTime.
the class ExamPeriodSwapMove method findBestAvailableRooms.
public Set<ExamRoomPlacement> findBestAvailableRooms(Assignment<Exam, ExamPlacement> assignment, Exam exam, ExamPeriodPlacement period, Set<ExamPlacement> conflictsToIgnore, Map<Exam, ExamPlacement> placements) {
if (exam.getMaxRooms() == 0)
return new HashSet<ExamRoomPlacement>();
double sw = exam.getModel().getCriterion(RoomSizePenalty.class).getWeight();
double pw = exam.getModel().getCriterion(RoomPenalty.class).getWeight();
double cw = exam.getModel().getCriterion(DistributionPenalty.class).getWeight();
ExamRoomSharing sharing = ((ExamModel) exam.getModel()).getRoomSharing();
loop: for (int nrRooms = 1; nrRooms <= exam.getMaxRooms(); nrRooms++) {
HashSet<ExamRoomPlacement> rooms = new HashSet<ExamRoomPlacement>();
int size = 0;
while (rooms.size() < nrRooms && size < exam.getSize()) {
int minSize = (exam.getSize() - size) / (nrRooms - rooms.size());
ExamRoomPlacement best = null;
double bestWeight = 0;
int bestSize = 0;
for (ExamRoomPlacement room : exam.getRoomPlacements()) {
if (!room.isAvailable(period.getPeriod()))
continue;
if (rooms.contains(room))
continue;
List<ExamPlacement> overlaps = new ArrayList<ExamPlacement>();
for (ExamPlacement overlap : room.getRoom().getPlacements(assignment, period.getPeriod())) if (!conflictsToIgnore.contains(overlap))
overlaps.add(overlap);
for (ExamPlacement other : placements.values()) if (other.getPeriod().equals(period.getPeriod()))
for (ExamRoomPlacement r : other.getRoomPlacements()) if (r.getRoom().equals(room.getRoom())) {
overlaps.add(other);
continue;
}
if (nrRooms == 1 && sharing != null) {
if (sharing.inConflict(exam, overlaps, room.getRoom()))
continue;
} else {
if (!overlaps.isEmpty())
continue;
}
if (iCheckDistributionConstraints && !checkDistributionConstraints(assignment, exam, room, conflictsToIgnore, placements))
continue;
int s = room.getSize(exam.hasAltSeating());
if (s < minSize)
break;
int p = room.getPenalty(period.getPeriod());
double w = pw * p + sw * (s - minSize) + cw * getDistributionConstraintPenalty(assignment, exam, room, conflictsToIgnore, placements);
double d = 0;
if (!rooms.isEmpty()) {
for (ExamRoomPlacement r : rooms) {
d += r.getDistanceInMeters(room);
}
w += d / rooms.size();
}
if (best == null || bestWeight > w) {
best = room;
bestSize = s;
bestWeight = w;
}
}
if (best == null)
continue loop;
rooms.add(best);
size += bestSize;
}
if (size >= exam.getSize())
return rooms;
}
return null;
}
use of org.cpsolver.exam.model.ExamPlacement in project cpsolver by UniTime.
the class ExamNeighbourSelection method selectNeighbour.
/**
* Neighbour selection. It consists of the following three phases:
* <ul>
* <li>Construction phase ({@link ExamConstruction} until all exams are
* assigned)
* <li>Hill-climbing phase ({@link HillClimber} until the given number
* if idle iterations)
* <li>Simulated annealing phase ({@link SimulatedAnnealing} until
* timeout is reached)
* </ul>
*/
@SuppressWarnings("fallthrough")
@Override
public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) {
Neighbour<Exam, ExamPlacement> n = null;
if (!isFinalPhase() && !iTerm.canContinue(solution))
setFinalPhase(null);
Context phase = getContext(solution.getAssignment());
if (isFinalPhase())
phase.setPhase(9999);
switch(phase.getPhase()) {
case -1:
phase.setPhase(0);
sLog.info("***** construction phase *****");
if (iColor != null) {
n = iColor.selectNeighbour(solution);
if (n != null)
return n;
}
case 0:
n = iCon.selectNeighbour(solution);
if (n != null)
return n;
if (solution.getAssignment().nrAssignedVariables() > 0)
iProgress.setPhase("Searching for initial solution...", solution.getModel().variables().size());
phase.setPhase(1);
sLog.info("***** cbs/tabu-search phase *****");
case 1:
if (iStd != null && solution.getModel().variables().size() > solution.getAssignment().nrAssignedVariables()) {
iProgress.setProgress(solution.getModel().variables().size() - solution.getModel().getBestUnassignedVariables());
n = iStd.selectNeighbour(solution);
if (n != null)
return n;
}
phase.setPhase(2);
sLog.info("***** hill climbing phase *****");
case 2:
n = iHC.selectNeighbour(solution);
if (n != null)
return n;
phase.setPhase(3);
sLog.info("***** " + (iUseGD ? "great deluge" : "simulated annealing") + " phase *****");
case 3:
if (iUseGD)
return iGD.selectNeighbour(solution);
else
return iSA.selectNeighbour(solution);
case 9999:
n = iFin.selectNeighbour(solution);
if (n != null)
return n;
phase.setPhase(-1);
if (iFinalPhaseFinished != null && iTerm.canContinue(solution))
iFinalPhaseFinished.execute();
phase.setCanContinue(false);
default:
return null;
}
}
use of org.cpsolver.exam.model.ExamPlacement in project cpsolver by UniTime.
the class ExamSimulatedAnnealing method selectNeighbour.
/**
* Select neighbour -- generate a move
* {@link ExamSimulatedAnnealing#genMove(Solution)} until an acceptable
* neighbour is found
* {@link ExamSimulatedAnnealing#accept(Solution, Neighbour)}, keep
* increasing iteration {@link ExamSimulatedAnnealing.Context#incIter(Solution)}.
*/
@Override
public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) {
Context context = getContext(solution.getAssignment());
context.activateIfNeeded();
Neighbour<Exam, ExamPlacement> neighbour = null;
while ((neighbour = genMove(solution)) != null) {
context.incMoves(neighbour.value(solution.getAssignment()));
if (accept(solution, neighbour))
break;
}
if (neighbour == null)
context.reset();
return (neighbour == null ? null : neighbour);
}
Aggregations