use of org.cpsolver.exam.model.ExamRoomSharing 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.ExamRoomSharing in project cpsolver by UniTime.
the class ExamTimeMove method selectNeighbour.
/**
* Select an exam randomly,
* select an available period randomly (if it is not assigned),
* use rooms if possible, select rooms using {@link Exam#findBestAvailableRooms(Assignment, ExamPeriodPlacement)} if not (exam is unassigned, a room is not available or used).
*/
@Override
public Neighbour<Exam, ExamPlacement> selectNeighbour(Solution<Exam, ExamPlacement> solution) {
ExamModel model = (ExamModel) solution.getModel();
Assignment<Exam, ExamPlacement> assignment = solution.getAssignment();
ExamRoomSharing sharing = model.getRoomSharing();
Exam exam = ToolBox.random(model.variables());
ExamPlacement placement = assignment.getValue(exam);
int px = ToolBox.random(exam.getPeriodPlacements().size());
for (int p = 0; p < exam.getPeriodPlacements().size(); p++) {
ExamPeriodPlacement period = exam.getPeriodPlacements().get((p + px) % exam.getPeriodPlacements().size());
if (placement != null && placement.getPeriod().equals(period))
continue;
if (iCheckStudentConflicts && exam.countStudentConflicts(assignment, period) > 0)
continue;
if (iCheckDistributionConstraints && !exam.checkDistributionConstraints(assignment, period))
continue;
if (placement != null) {
boolean ok = true;
if (sharing != null && placement.getRoomPlacements().size() == 1) {
ExamRoomPlacement room = placement.getRoomPlacements().iterator().next();
ok = room.isAvailable(period.getPeriod()) && !sharing.inConflict(exam, room.getRoom().getPlacements(assignment, period.getPeriod()), room.getRoom());
} else {
for (Iterator<ExamRoomPlacement> i = placement.getRoomPlacements().iterator(); i.hasNext(); ) {
ExamRoomPlacement room = i.next();
if (!room.isAvailable(period.getPeriod()) || !room.getRoom().getPlacements(assignment, period.getPeriod()).isEmpty()) {
ok = false;
break;
}
}
}
if (ok)
return new ExamSimpleNeighbour(assignment, new ExamPlacement(exam, period, placement.getRoomPlacements()));
}
Set<ExamRoomPlacement> rooms = exam.findBestAvailableRooms(assignment, period);
if (rooms == null)
continue;
return new ExamSimpleNeighbour(assignment, new ExamPlacement(exam, period, rooms));
}
return null;
}
Aggregations