use of org.cpsolver.coursett.model.Placement 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.Placement in project cpsolver by UniTime.
the class BreakFlexibleConstraint method computeConflicts.
@Override
public void computeConflicts(Assignment<Lecture, Placement> assignment, Placement value, Set<Placement> conflicts) {
if (!isHard())
return;
List<BitSet> weeks = getWeeks();
// checks only placements in the break time
if (value.getTimeLocation().getStartSlot() <= iBreakEnd && value.getTimeLocation().getStartSlot() + value.getTimeLocation().getLength() > iBreakStart) {
for (int dayCode : Constants.DAY_CODES) {
// checks only days affected by the placement
if ((value.getTimeLocation().getDayCode() & dayCode) != 0) {
// constraint is checked for every week in semester (or for the whole semester)
for (BitSet week : weeks) {
boolean isProblem = false;
do {
Set<Placement> adepts = new HashSet<Placement>();
// each blocks contains placements which are BTB
// placements are BTB if there is less time between them than the minimal break length
List<Block> blocks = getBreakBlocks(assignment, dayCode, conflicts, value, null, week);
// determine possible conflicts from blocks' placements
getAdeptsLunchBreak(blocks, adepts);
if (adepts.isEmpty())
isProblem = false;
// currently assigned value shouldn't be added to conflicts if possible
if (adepts.size() >= 2)
adepts.remove(value);
// pick random placement
Placement conflict = ToolBox.random(adepts);
if (conflict != null) {
conflicts.add(conflict);
}
} while (isProblem);
}
}
}
}
}
use of org.cpsolver.coursett.model.Placement in project cpsolver by UniTime.
the class BreakFlexibleConstraint method getAdeptsLunchBreak.
/**
* Method adds Placements from blocks to adepts if there is a possibility, that the placement caused constraint violation
*
* @param blocks placements in
* @param adepts
*/
private void getAdeptsLunchBreak(List<Block> blocks, Set<Placement> adepts) {
List<Block> matchingBlocks = new ArrayList<Block>();
for (Block block : blocks) {
// if block intersects with break interval, it will be used in conflict selection
if (block.getStartSlotCurrentBlock() <= iBreakEnd && block.getEndSlotCurrentBlock() >= iBreakStart)
matchingBlocks.add(block);
}
int size = matchingBlocks.size();
// if there is only one block intersecting with break interval, constraint might not be satisfied
if (size == 1) {
Block block = matchingBlocks.get(0);
// check whether the block leaves enough space for break
if (block.getStartSlotCurrentBlock() - iBreakStart >= iBreakLength || iBreakEnd - block.getEndSlotCurrentBlock() >= iBreakLength) {
return;
// if it doesn't
} else {
// every placement intersecting with break interval might be potential conflict
for (Placement p : block.getPlacements()) {
if (p.getTimeLocation().getStartSlot() <= iBreakEnd && p.getTimeLocation().getStartSlot() + p.getTimeLocation().getLength() >= iBreakStart) {
adepts.add(p);
}
}
}
}
}
use of org.cpsolver.coursett.model.Placement 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);
}
}
use of org.cpsolver.coursett.model.Placement in project cpsolver by UniTime.
the class GroupConstraint method forwardCheck.
public void forwardCheck(Assignment<Lecture, Placement> assignment, Placement value, Set<Placement> conflicts, Set<GroupConstraint> ignore, int depth) {
try {
if (depth < 0)
return;
ignore.add(this);
int neededSize = value.variable().maxRoomUse();
for (Lecture lecture : variables()) {
// already conflicting
if (conflicts.contains(value))
break;
// 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;
}
conflicts.add(current);
}
// Look for supporting assignments assignment
boolean shareRoomAndOverlaps = canShareRoom();
Placement support = null;
int nrSupports = 0;
if (lecture.nrValues() >= iForwardCheckMaxDomainSize) {
// ignore variables with large domains
return;
}
List<Placement> values = lecture.values(assignment);
if (values.isEmpty()) {
// ignore variables with empty domain
return;
}
for (Placement other : values) {
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
conflicts.add(value);
return;
}
// 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, conflicts, ignore, depth - 1);
} else {
other.computeConflicts(assignment, support, conflicts);
}
}
for (GlobalConstraint<Lecture, Placement> other : getModel().globalConstraints()) {
if (other instanceof WeakeningConstraint)
continue;
other.computeConflicts(assignment, support, conflicts);
}
if (conflicts.contains(support))
conflicts.add(value);
}
}
if (canShareRoom() && neededSize > value.getRoomSize()) {
// room is too small to fit all meet with classes
conflicts.add(value);
}
} finally {
ignore.remove(this);
}
}
Aggregations