use of org.cpsolver.studentsct.model.Enrollment in project cpsolver by UniTime.
the class SectionLimit method computeConflicts.
/**
* A given enrollment is conflicting, if there is a section which limit
* (computed by {@link SectionLimit#getEnrollmentWeight(Assignment, Section, Request)})
* exceeds the section limit. <br>
* For each of such sections, one or more existing enrollments are
* (randomly) selected as conflicting until the overall weight is under the
* limit.
*
* @param enrollment
* {@link Enrollment} that is being considered
* @param conflicts
* all computed conflicting requests are added into this set
*/
@Override
public void computeConflicts(Assignment<Request, Enrollment> assignment, Enrollment enrollment, Set<Enrollment> conflicts) {
// check reservation can assign over the limit
if (enrollment.getReservation() != null && enrollment.getReservation().canBatchAssignOverLimit())
return;
// exclude free time requests
if (!enrollment.isCourseRequest())
return;
// for each section
for (Section section : enrollment.getSections()) {
// no reservation -- check the space in the unreserved space in the section
if (enrollment.getConfig().getOffering().hasReservations() && !hasSectionReservation(enrollment, section)) {
// section is fully reserved by section reservations
if (section.getTotalUnreservedSpace() < enrollment.getRequest().getWeight()) {
conflicts.add(enrollment);
return;
}
double unreserved = getUnreservedSpace(assignment, section, enrollment.getRequest());
if (unreserved < 0.0) {
// no unreserved space available -> cannot be assigned
// try to unassign some other enrollments that also do not have reservation
List<Enrollment> adepts = new ArrayList<Enrollment>(section.getEnrollments(assignment).size());
for (Enrollment e : section.getEnrollments(assignment)) {
if (e.getRequest().equals(enrollment.getRequest()))
continue;
if (e.getReservation() != null && e.getReservation().canBatchAssignOverLimit())
continue;
if (hasSectionReservation(e, section))
continue;
if (conflicts.contains(e))
unreserved += e.getRequest().getWeight();
else
adepts.add(e);
}
while (unreserved < 0.0) {
if (adepts.isEmpty()) {
// no adepts -> enrollment cannot be assigned
conflicts.add(enrollment);
return;
}
// pick adept (prefer dummy students), decrease unreserved space,
// make conflict
List<Enrollment> best = new ArrayList<Enrollment>();
boolean bestDummy = false;
double bestValue = 0;
for (Enrollment adept : adepts) {
boolean dummy = adept.getStudent().isDummy();
double value = adept.toDouble(assignment, false);
if (iPreferDummyStudents && dummy != bestDummy) {
if (dummy) {
best.clear();
best.add(adept);
bestDummy = dummy;
bestValue = value;
}
continue;
}
if (best.isEmpty() || value > bestValue) {
if (best.isEmpty())
best.clear();
best.add(adept);
bestDummy = dummy;
bestValue = value;
} else if (bestValue == value) {
best.add(adept);
}
}
Enrollment conflict = ToolBox.random(best);
adepts.remove(conflict);
unreserved += conflict.getRequest().getWeight();
conflicts.add(conflict);
}
}
}
// unlimited section
if (section.getLimit() < 0)
continue;
// new enrollment weight
double enrlWeight = getEnrollmentWeight(assignment, section, enrollment.getRequest());
// below limit -> ok
if (enrlWeight <= section.getLimit())
continue;
// above limit -> compute adepts (current assignments that are not
// yet conflicting) exclude all conflicts as well
List<Enrollment> adepts = new ArrayList<Enrollment>(section.getEnrollments(assignment).size());
for (Enrollment e : section.getEnrollments(assignment)) {
if (e.getRequest().equals(enrollment.getRequest()))
continue;
if (conflicts.contains(e))
enrlWeight -= e.getRequest().getWeight();
else
adepts.add(e);
}
// while above limit -> pick an adept and make it conflicting
while (enrlWeight > section.getLimit()) {
if (adepts.isEmpty()) {
// no adepts -> enrollment cannot be assigned
conflicts.add(enrollment);
return;
}
// pick adept (prefer dummy students & students w/o reservation), decrease enrollment
// weight, make conflict
List<Enrollment> best = new ArrayList<Enrollment>();
boolean bestDummy = false;
double bestValue = 0;
boolean bestRes = true;
for (Enrollment adept : adepts) {
boolean dummy = adept.getStudent().isDummy();
double value = adept.toDouble(assignment, false);
boolean res = hasSectionReservation(adept, section);
if (iPreferDummyStudents && dummy != bestDummy) {
if (dummy) {
best.clear();
best.add(adept);
bestDummy = dummy;
bestValue = value;
bestRes = res;
}
continue;
}
if (bestRes != res) {
if (!res) {
best.clear();
best.add(adept);
bestDummy = dummy;
bestValue = value;
bestRes = res;
}
continue;
}
if (best.isEmpty() || value > bestValue) {
if (best.isEmpty())
best.clear();
best.add(adept);
bestDummy = dummy;
bestValue = value;
bestRes = res;
} else if (bestValue == value) {
best.add(adept);
}
}
Enrollment conflict = ToolBox.random(best);
adepts.remove(conflict);
enrlWeight -= conflict.getRequest().getWeight();
conflicts.add(conflict);
}
}
}
use of org.cpsolver.studentsct.model.Enrollment in project cpsolver by UniTime.
the class EnrollmentSelection method isAllowed.
/** true, if it is allowed to assign given value
* @param assignment current assignment
* @param value given value
* @param conflicts conflicting assignments
* @return true if it is allowed
**/
public boolean isAllowed(Assignment<Request, Enrollment> assignment, Enrollment value, Set<Enrollment> conflicts) {
if (value == null)
return true;
StudentSectioningModel model = (StudentSectioningModel) value.variable().getModel();
if (model.getNrLastLikeRequests(false) == 0 || model.getNrRealRequests(false) == 0)
return true;
Request request = value.variable();
if (request.getStudent().isDummy()) {
if (conflicts == null)
conflicts = value.variable().getModel().conflictValues(assignment, value);
for (Enrollment conflict : conflicts) {
if (!conflict.getRequest().getStudent().isDummy())
return false;
}
} else {
if (conflicts == null)
conflicts = value.variable().getModel().conflictValues(assignment, value);
if (conflicts.size() > (assignment.getValue(request) == null ? 1 : 0))
return false;
}
return true;
}
use of org.cpsolver.studentsct.model.Enrollment in project cpsolver by UniTime.
the class OnlineSelection method updateSpace.
/** Update online sectioning info after the given student is sectioned
* @param assignment current assignment
* @param student student in question
**/
public void updateSpace(Assignment<Request, Enrollment> assignment, Student student) {
for (Request request : student.getRequests()) {
if (!(request instanceof CourseRequest))
continue;
CourseRequest courseRequest = (CourseRequest) request;
Enrollment enrollment = assignment.getValue(courseRequest);
if (enrollment == null)
// not enrolled --> no update
return;
for (Section section : enrollment.getSections()) {
section.setSpaceHeld(section.getSpaceHeld() - courseRequest.getWeight());
// sLog.debug(" -- space held for "+section+" decreased by 1 (to "+section.getSpaceHeld()+")");
}
List<Enrollment> feasibleEnrollments = new ArrayList<Enrollment>();
for (Enrollment enrl : courseRequest.values(assignment)) {
boolean overlaps = false;
for (Request otherRequest : courseRequest.getStudent().getRequests()) {
if (otherRequest.equals(courseRequest) || !(otherRequest instanceof CourseRequest))
continue;
Enrollment otherErollment = assignment.getValue(otherRequest);
if (otherErollment == null)
continue;
if (enrl.isOverlapping(otherErollment)) {
overlaps = true;
break;
}
}
if (!overlaps)
feasibleEnrollments.add(enrl);
}
double decrement = courseRequest.getWeight() / feasibleEnrollments.size();
for (Enrollment feasibleEnrollment : feasibleEnrollments) {
for (Section section : feasibleEnrollment.getSections()) {
section.setSpaceExpected(section.getSpaceExpected() - decrement);
// sLog.debug(" -- space expected for "+section+" decreased by "+decrement+" (to "+section.getSpaceExpected()+")");
}
}
}
}
use of org.cpsolver.studentsct.model.Enrollment in project cpsolver by UniTime.
the class PriorityConstructionSelection method branchAndBound.
/**
* Find best solution for the next student using {@link BranchBoundSelection}.
* @param solution current selection
* @return generated neighbour
*/
public Neighbour<Request, Enrollment> branchAndBound(Solution<Request, Enrollment> solution) {
while (iStudentsEnumeration.hasNext()) {
Student student = iStudentsEnumeration.next();
Progress.getInstance(solution.getModel()).incProgress();
/*
if (student.nrRequests() < iCycle) {
// not enough requests -> nothing to improve -> skip
continue;
}
if (student.nrAssignedRequests() + 1 < iCycle) {
// previous step cycle already did not improve the assignment -> skip
continue;
}
*/
Neighbour<Request, Enrollment> neighbour = iBranchBoundSelection.getSelection(solution.getAssignment(), student).select();
if (neighbour != null)
return neighbour;
}
return null;
}
Aggregations