use of org.cpsolver.coursett.model.Lecture in project cpsolver by UniTime.
the class TimetableSolver method fixCompleteSolution.
/**
* Try to improve existing solution by backtracking search of very limited
* depth. See {@link NeighbourSelectionWithSuggestions} for more details.
* @param solution current solution
* @param startTime start time
*/
protected void fixCompleteSolution(Solution<Lecture, Placement> solution, double startTime) {
Progress progress = Progress.getInstance(solution.getModel());
TimetableModel model = (TimetableModel) solution.getModel();
Assignment<Lecture, Placement> assignment = solution.getAssignment();
solution.saveBest();
progress.save();
double solutionValue = 0.0, newSolutionValue = model.getTotalValue(assignment);
do {
solutionValue = newSolutionValue;
progress.setPhase("Fixing solution", model.variables().size());
for (Lecture variable : model.variables()) {
Placement bestValue = null;
double bestVal = 0.0;
Placement currentValue = assignment.getValue(variable);
if (currentValue == null)
continue;
double currentVal = currentValue.toDouble(assignment);
for (Placement value : variable.values()) {
if (value.equals(currentValue))
continue;
if (model.conflictValues(assignment, value).isEmpty()) {
double val = value.toDouble(assignment);
if (bestValue == null || val < bestVal) {
bestValue = value;
bestVal = val;
}
}
}
if (bestValue != null && bestVal < currentVal)
assignment.assign(0, bestValue);
solution.update(JProf.currentTimeSec() - startTime);
progress.incProgress();
if (iStop)
break;
}
newSolutionValue = model.getTotalValue(assignment);
if (newSolutionValue < solutionValue) {
progress.debug("New solution value is " + newSolutionValue);
}
} while (!iStop && newSolutionValue < solutionValue && getTerminationCondition().canContinue(solution));
progress.restore();
if (!solution.getModel().unassignedVariables(assignment).isEmpty())
return;
progress.save();
try {
progress.setPhase("Fixing solution [2]", model.variables().size());
NeighbourSelectionWithSuggestions ns = new NeighbourSelectionWithSuggestions(this);
for (Lecture lecture : model.variables()) {
Neighbour<Lecture, Placement> n = ns.selectNeighbourWithSuggestions(solution, lecture, 2);
if (n != null && n.value(assignment) <= 0.0)
n.assign(assignment, 0);
solution.update(JProf.currentTimeSec() - startTime);
progress.incProgress();
if (iStop)
break;
}
} catch (Exception e) {
sLogger.debug(e.getMessage(), e);
} finally {
progress.restore();
}
}
use of org.cpsolver.coursett.model.Lecture in project cpsolver by UniTime.
the class GroupConstraint method toString.
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(getName());
sb.append(" between ");
for (Iterator<Lecture> e = variables().iterator(); e.hasNext(); ) {
Lecture v = e.next();
sb.append(v.getName());
if (e.hasNext())
sb.append(", ");
}
return sb.toString();
}
use of org.cpsolver.coursett.model.Lecture in project cpsolver by UniTime.
the class Test method printClassInfo.
/** Class information
* @param pw writer
* @param model problem model
**/
public static void printClassInfo(PrintWriter pw, TimetableModel model) {
pw.println("Class info:");
pw.println("id, name, min_class_limit, max_class_limit, room2limit_ratio, half_hours");
for (Lecture lecture : model.variables()) {
TimeLocation time = lecture.timeLocations().get(0);
pw.println(lecture.getClassId() + "," + lecture.getName() + "," + lecture.minClassLimit() + "," + lecture.maxClassLimit() + "," + lecture.roomToLimitRatio() + "," + (time.getNrSlotsPerMeeting() * time.getNrMeetings()));
}
}
use of org.cpsolver.coursett.model.Lecture in project cpsolver by UniTime.
the class InstructorConstraint method getPreferenceCombination.
public int getPreferenceCombination(Assignment<Lecture, Placement> assignment, Placement value) {
Lecture lecture = value.variable();
Placement placement = value;
int pref = 0;
HashSet<Placement> checked = new HashSet<Placement>();
InstructorConstraintContext context = getContext(assignment);
for (Enumeration<Integer> e = placement.getTimeLocation().getStartSlots(); e.hasMoreElements(); ) {
int startSlot = e.nextElement();
int prevSlot = startSlot - 1;
if (prevSlot >= 0 && (prevSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) {
for (Placement c : context.getPlacements(prevSlot, placement)) {
if (lecture.equals(c.variable()) || !checked.add(c))
continue;
double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c);
if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit())
pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged);
if (dist > getDistanceMetric().getInstructorDiscouragedLimit() && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances))
pref = Math.max(pref, Constants.sPreferenceLevelStronglyDiscouraged);
if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit())
pref = Math.max(pref, Constants.sPreferenceLevelProhibited);
}
}
int nextSlot = startSlot + placement.getTimeLocation().getLength();
if ((nextSlot / Constants.SLOTS_PER_DAY) == (startSlot / Constants.SLOTS_PER_DAY)) {
for (Placement c : context.getPlacements(nextSlot, placement)) {
if (lecture.equals(c.variable()) || !checked.add(c))
continue;
double dist = Placement.getDistanceInMeters(getDistanceMetric(), placement, c);
if (dist > getDistanceMetric().getInstructorNoPreferenceLimit() && dist <= getDistanceMetric().getInstructorDiscouragedLimit())
pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged);
if (dist > getDistanceMetric().getInstructorDiscouragedLimit() && (dist <= getDistanceMetric().getInstructorProhibitedLimit() || iIgnoreDistances))
pref = Math.max(pref, Constants.sPreferenceLevelStronglyDiscouraged);
if (!iIgnoreDistances && dist > getDistanceMetric().getInstructorProhibitedLimit())
pref = Constants.sPreferenceLevelProhibited;
}
}
if (getDistanceMetric().doComputeDistanceConflictsBetweenNonBTBClasses()) {
TimeLocation t1 = placement.getTimeLocation();
Placement before = null, after = null;
for (Lecture other : variables()) {
Placement otherPlacement = assignment.getValue(other);
if (otherPlacement == null || other.equals(placement.variable()))
continue;
TimeLocation t2 = otherPlacement.getTimeLocation();
if (t1 == null || t2 == null || !t1.shareDays(t2) || !t1.shareWeeks(t2))
continue;
if (t1.getStartSlot() + t1.getLength() < t2.getStartSlot()) {
int distanceInMinutes = Placement.getDistanceInMinutes(getDistanceMetric(), placement, otherPlacement);
if (distanceInMinutes > t1.getBreakTime() + Constants.SLOT_LENGTH_MIN * (t2.getStartSlot() - t1.getStartSlot() - t1.getLength()))
pref = Math.max(pref, (iIgnoreDistances ? Constants.sPreferenceLevelStronglyDiscouraged : Constants.sPreferenceLevelProhibited));
else if (distanceInMinutes > Constants.SLOT_LENGTH_MIN * (t2.getStartSlot() - t1.getStartSlot() - t1.getLength()))
pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged);
} else if (t2.getStartSlot() + t2.getLength() < t1.getStartSlot()) {
int distanceInMinutes = Placement.getDistanceInMinutes(getDistanceMetric(), placement, otherPlacement);
if (distanceInMinutes > t2.getBreakTime() + Constants.SLOT_LENGTH_MIN * (t1.getStartSlot() - t2.getStartSlot() - t2.getLength()))
pref = Math.max(pref, (iIgnoreDistances ? Constants.sPreferenceLevelStronglyDiscouraged : Constants.sPreferenceLevelProhibited));
else if (distanceInMinutes > Constants.SLOT_LENGTH_MIN * (t1.getStartSlot() - t2.getStartSlot() - t2.getLength()))
pref = Math.max(pref, Constants.sPreferenceLevelDiscouraged);
}
if (t1.getStartSlot() + t1.getLength() <= t2.getStartSlot()) {
if (after == null || t2.getStartSlot() < after.getTimeLocation().getStartSlot())
after = otherPlacement;
} else if (t2.getStartSlot() + t2.getLength() <= t1.getStartSlot()) {
if (before == null || before.getTimeLocation().getStartSlot() < t2.getStartSlot())
before = otherPlacement;
}
}
if (iUnavailabilities != null) {
for (Placement c : iUnavailabilities) {
TimeLocation t2 = c.getTimeLocation();
if (t1 == null || t2 == null || !t1.shareDays(t2) || !t1.shareWeeks(t2))
continue;
if (t1.getStartSlot() + t1.getLength() <= t2.getStartSlot()) {
if (after == null || t2.getStartSlot() < after.getTimeLocation().getStartSlot())
after = c;
} else if (t2.getStartSlot() + t2.getLength() <= t1.getStartSlot()) {
if (before == null || before.getTimeLocation().getStartSlot() < t2.getStartSlot())
before = c;
}
}
}
int tooLongTravel = 0;
if (before != null && Placement.getDistanceInMinutes(getDistanceMetric(), before, placement) > getDistanceMetric().getInstructorLongTravelInMinutes())
tooLongTravel++;
if (after != null && Placement.getDistanceInMinutes(getDistanceMetric(), after, placement) > getDistanceMetric().getInstructorLongTravelInMinutes())
tooLongTravel++;
if (tooLongTravel > 0)
pref += Math.max(pref, Constants.sPreferenceLevelStronglyDiscouraged);
}
}
return pref;
}
use of org.cpsolver.coursett.model.Lecture in project cpsolver by UniTime.
the class GroupConstraint method forwardCheck.
public boolean forwardCheck(Assignment<Lecture, Placement> assignment, Placement value, Set<GroupConstraint> ignore, int depth) {
try {
if (depth < 0)
return true;
ignore.add(this);
int neededSize = value.variable().maxRoomUse();
for (Lecture lecture : variables()) {
// Skip this lecture
if (lecture.equals(value.variable()))
continue;
Placement current = assignment.getValue(lecture);
if (current != null) {
// Has assignment, check whether it is conflicting
if (isSatisfiedPair(assignment, value, current)) {
// Increase needed size if the assignment is of the same room and overlapping in time
if (canShareRoom() && sameRoomAndOverlaps(value, current)) {
neededSize += lecture.maxRoomUse();
}
continue;
}
return false;
}
// Look for supporting assignments assignment
boolean shareRoomAndOverlaps = canShareRoom();
Placement support = null;
int nrSupports = 0;
if (lecture.nrValues() >= iForwardCheckMaxDomainSize) {
// ignore variables with large domains
return true;
}
List<Placement> values = lecture.values(assignment);
if (values.isEmpty()) {
// ignore variables with empty domain
return true;
}
for (Placement other : lecture.values(assignment)) {
if (nrSupports < 2) {
if (isSatisfiedPair(assignment, value, other)) {
if (support == null)
support = other;
nrSupports++;
if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other))
shareRoomAndOverlaps = false;
}
} else if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other) && isSatisfiedPair(assignment, value, other)) {
shareRoomAndOverlaps = false;
}
if (nrSupports > 1 && !shareRoomAndOverlaps)
break;
}
// No supporting assignment -> fail
if (nrSupports == 0) {
// other class cannot be assigned with this value
return false;
}
// Increase needed size if all supporters are of the same room and in overlapping times
if (shareRoomAndOverlaps) {
neededSize += lecture.maxRoomUse();
}
// Only one supporter -> propagate the new assignment over other hard constraints of the lecture
if (nrSupports == 1) {
for (Constraint<Lecture, Placement> other : lecture.hardConstraints()) {
if (other instanceof WeakeningConstraint)
continue;
if (other instanceof GroupConstraint) {
GroupConstraint gc = (GroupConstraint) other;
if (depth > 0 && !ignore.contains(gc) && !gc.forwardCheck(assignment, support, ignore, depth - 1))
return false;
} else {
if (other.inConflict(assignment, support))
return false;
}
}
for (GlobalConstraint<Lecture, Placement> other : getModel().globalConstraints()) {
if (other instanceof WeakeningConstraint)
continue;
if (other.inConflict(assignment, support))
return false;
}
}
}
if (canShareRoom() && neededSize > value.getRoomSize()) {
// room is too small to fit all meet with classes
return false;
}
return true;
} finally {
ignore.remove(this);
}
}
Aggregations