use of org.cpsolver.exam.model.Exam in project cpsolver by UniTime.
the class StudentDistanceBackToBackConflicts method getValue.
@Override
public double getValue(Assignment<Exam, ExamPlacement> assignment, ExamPlacement value, Set<ExamPlacement> conflicts) {
Exam exam = value.variable();
if (getBackToBackDistance() < 0)
return 0;
int penalty = 0;
ExamPeriod period = value.getPeriod();
Map<ExamStudent, Set<Exam>> prev = (period.prev() != null && period.prev().getDay() == period.getDay() ? ((ExamModel) getModel()).getStudentsOfPeriod(assignment, period.prev()) : null);
Map<ExamStudent, Set<Exam>> next = (period.next() != null && period.next().getDay() == period.getDay() ? ((ExamModel) getModel()).getStudentsOfPeriod(assignment, period.next()) : null);
for (ExamStudent s : exam.getStudents()) {
if (prev != null) {
Set<Exam> exams = prev.get(s);
if (exams != null)
for (Exam x : exams) {
if (x.equals(exam))
continue;
if (value.getDistanceInMeters(assignment.getValue(x)) > getBackToBackDistance())
penalty++;
}
}
if (next != null) {
Set<Exam> exams = next.get(s);
if (exams != null)
for (Exam x : exams) {
if (x.equals(exam))
continue;
if (value.getDistanceInMeters(assignment.getValue(x)) > getBackToBackDistance())
penalty++;
}
}
}
/*
for (ExamStudent s : exam.getStudents()) {
if (period.prev() != null) {
if (period.prev().getDay() == period.getDay()) {
for (Exam x : s.getExams(assignment, period.prev())) {
if (x.equals(exam))
continue;
if (value.getDistanceInMeters(assignment.getValue(x)) > getBackToBackDistance())
penalty++;
}
}
}
if (period.next() != null) {
if (period.next().getDay() == period.getDay()) {
for (Exam x : s.getExams(assignment, period.next())) {
if (x.equals(exam))
continue;
if (value.getDistanceInMeters(assignment.getValue(x)) > getBackToBackDistance())
penalty++;
}
}
}
}
*/
return penalty;
}
use of org.cpsolver.exam.model.Exam in project cpsolver by UniTime.
the class ExamSplitter method shuffle.
/**
* Shuffle students between the given exam and all the other exams in the split (if there are any).
* Only moves between exams that improve {@link ExamSplitter#delta(Assignment, ExamStudent, ExamPlacement, ExamPlacement)} are
* considered.
* @param assignment current assignment
* @param exam an exam in question
* @param iteration solver iteration
*/
public void shuffle(Assignment<Exam, ExamPlacement> assignment, Exam exam, long iteration) {
// Parent exam (its either the exam itself, or its parent if it has been already split)
Exam parent = (iParent.containsKey(exam) ? iParent.get(exam) : exam);
// Its children (if already split)
List<Exam> children = iChildren.get(parent);
if (children != null && !children.isEmpty()) {
// Unassign all involved exams
Map<Exam, ExamPlacement> assignments = new HashMap<Exam, ExamPlacement>();
if (assignment.getValue(parent) != null) {
assignments.put(parent, assignment.getValue(parent));
assignment.unassign(iteration, parent);
}
for (Exam child : children) {
if (assignment.getValue(child) != null) {
assignments.put(child, assignment.getValue(child));
assignment.unassign(iteration, child);
}
}
// Move away from parent
for (ExamStudent student : new ArrayList<ExamStudent>(parent.getStudents())) {
Exam child = null;
double delta = 0;
for (Exam x : children) {
double d = delta(assignment, student, assignments.get(parent), assignments.get(x));
if (child == null || d < delta) {
delta = d;
child = x;
}
}
if (child != null && delta < 0) {
student.removeVariable(parent);
student.addVariable(child);
}
}
// Move students away from a child
for (Exam child : children) {
for (ExamStudent student : new ArrayList<ExamStudent>(child.getStudents())) {
Exam other = parent;
double delta = delta(assignment, student, assignments.get(child), assignments.get(parent));
for (Exam x : children) {
if (x.equals(child))
continue;
double d = delta(assignment, student, assignments.get(child), assignments.get(x));
if (d < delta) {
delta = d;
other = x;
}
}
if (other != null && delta < 0) {
student.removeVariable(child);
student.addVariable(other);
}
}
}
// Assign everything back
ExamPlacement parentPlacement = assignments.get(parent);
if (parentPlacement != null)
assignment.assign(iteration, parentPlacement);
for (Exam child : children) {
ExamPlacement placement = assignments.get(child);
if (placement != null)
assignment.assign(iteration, placement);
}
}
}
use of org.cpsolver.exam.model.Exam in project cpsolver by UniTime.
the class ExamSplitter method bestSaved.
/** Best solution was saved, remember the current splits */
@Override
public void bestSaved(Assignment<Exam, ExamPlacement> assignment) {
super.bestSaved(assignment);
if (iBestSplit == null)
iBestSplit = new Hashtable<Exam, List<ExamPlacement>>();
else
iBestSplit.clear();
for (Map.Entry<Exam, List<Exam>> entry : iChildren.entrySet()) {
Exam parent = entry.getKey();
List<ExamPlacement> placements = new ArrayList<ExamPlacement>();
for (Exam child : entry.getValue()) {
if (assignment.getValue(child) != null)
placements.add(assignment.getValue(child));
}
if (!placements.isEmpty())
iBestSplit.put(parent, placements);
}
}
use of org.cpsolver.exam.model.Exam in project cpsolver by UniTime.
the class ExamSplitter method merge.
/**
* Merge an exam
* @param assignment current assignment
* @param child an exam to be merged
* @param iteration solver iteration
* @return parent exam of the exam that has been deleted; null if the given exam cannot be merged
*/
public Exam merge(Assignment<Exam, ExamPlacement> assignment, Exam child, long iteration) {
if (!canMerge(child))
return null;
// Update the parent and children structures
Exam parent = iParent.get(child);
iParent.remove(child);
List<Exam> children = iChildren.get(parent);
children.remove(child);
iValue -= 1.0;
// Unassign parent and the given exam
ExamPlacement parentPlacement = assignment.getValue(parent);
if (parentPlacement != null)
assignment.unassign(iteration, parent);
if (assignment.getValue(child) != null)
assignment.unassign(iteration, child);
// Move students back from the given exam
for (ExamStudent student : new ArrayList<ExamStudent>(child.getStudents())) {
student.removeVariable(child);
student.addVariable(parent);
}
// Remove the given exam from the model
for (ExamRoomPlacement room : child.getRoomPlacements()) room.getRoom().removeVariable(child);
parent.getModel().removeVariable(child);
// Assign parent exam back
if (parentPlacement != null)
assignment.assign(iteration, parentPlacement);
// Shuffle students between parent exam and its remaining children
shuffle(assignment, parent, iteration);
// Return parent exam
return parent;
}
use of org.cpsolver.exam.model.Exam in project cpsolver by UniTime.
the class ExamSplitter method split.
/**
* Split an exam
* @param assignment current assignment
* @param parent an exam to be split
* @param iteration solver iteration
* @param placement placement of the new exam
* @return new exam assigned to the given placement with students moved into it; null if the given exam cannot be split
*/
public Exam split(Assignment<Exam, ExamPlacement> assignment, Exam parent, long iteration, ExamPlacement placement) {
if (!canSplit(parent))
return null;
// Create the child exam
Exam child = new Exam(--iLastSplitId, parent.getName(), parent.getLength(), parent.hasAltSeating(), parent.getMaxRooms(), parent.getMinSize(), parent.getPeriodPlacements(), parent.getRoomPlacements());
child.setSizeOverride(parent.getSizeOverride());
child.setPrintOffset(parent.getPrintOffset());
child.setAveragePeriod(parent.getAveragePeriod());
child.getOwners().addAll(parent.getOwners());
// Update the parent and children structures
iParent.put(child, parent);
List<Exam> children = iChildren.get(parent);
if (children == null) {
children = new ArrayList<Exam>();
iChildren.put(parent, children);
}
children.add(child);
iValue += 1.0;
// Add into model
parent.getModel().addVariable(child);
for (ExamRoomPlacement room : child.getRoomPlacements()) room.getRoom().addVariable(child);
if (placement != null)
assignment.assign(iteration, new ExamPlacement(child, placement.getPeriodPlacement(), placement.getRoomPlacements()));
// Shuffle students between parent exam and its children
shuffle(assignment, parent, iteration);
// Return the new exam
return child;
}
Aggregations