use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class Test method updateSpace.
public static void updateSpace(Assignment<Request, Enrollment> assignment, Enrollment enrollment, boolean increment) {
if (enrollment == null || !enrollment.isCourseRequest())
return;
for (Section section : enrollment.getSections()) section.setSpaceHeld(section.getSpaceHeld() + (increment ? 1.0 : -1.0));
List<Enrollment> feasibleEnrollments = new ArrayList<Enrollment>();
int totalLimit = 0;
for (Enrollment enrl : enrollment.getRequest().values(assignment)) {
if (!enrl.getCourse().equals(enrollment.getCourse()))
continue;
boolean overlaps = false;
for (Request otherRequest : enrollment.getRequest().getStudent().getRequests()) {
if (otherRequest.equals(enrollment.getRequest()) || !(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);
if (totalLimit >= 0) {
int limit = enrl.getLimit();
if (limit < 0)
totalLimit = -1;
else
totalLimit += limit;
}
}
}
double change = enrollment.getRequest().getWeight() / (totalLimit > 0 ? totalLimit : feasibleEnrollments.size());
for (Enrollment feasibleEnrollment : feasibleEnrollments) for (Section section : feasibleEnrollment.getSections()) {
if (totalLimit > 0) {
section.setSpaceExpected(section.getSpaceExpected() + (increment ? +change : -change) * feasibleEnrollment.getLimit());
} else {
section.setSpaceExpected(section.getSpaceExpected() + (increment ? +change : -change));
}
}
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class Test method clone.
protected Course clone(Course course, long studentId, Student originalStudent, Map<Long, Section> classTable, StudentSectioningModel model) {
Offering clonedOffering = new Offering(course.getOffering().getId(), course.getOffering().getName());
clonedOffering.setModel(model);
int courseLimit = course.getLimit();
if (courseLimit >= 0) {
courseLimit -= course.getEnrollments(assignment()).size();
if (courseLimit < 0)
courseLimit = 0;
for (Iterator<Enrollment> i = course.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
courseLimit++;
break;
}
}
}
Course clonedCourse = new Course(course.getId(), course.getSubjectArea(), course.getCourseNumber(), clonedOffering, courseLimit, course.getProjected());
clonedCourse.setNote(course.getNote());
Hashtable<Config, Config> configs = new Hashtable<Config, Config>();
Hashtable<Subpart, Subpart> subparts = new Hashtable<Subpart, Subpart>();
Hashtable<Section, Section> sections = new Hashtable<Section, Section>();
for (Iterator<Config> e = course.getOffering().getConfigs().iterator(); e.hasNext(); ) {
Config config = e.next();
int configLimit = config.getLimit();
int configEnrollment = config.getEnrollments(assignment()).size();
if (configLimit >= 0) {
configLimit -= config.getEnrollments(assignment()).size();
if (configLimit < 0)
configLimit = 0;
for (Iterator<Enrollment> i = config.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
configLimit++;
configEnrollment--;
break;
}
}
}
OnlineConfig clonedConfig = new OnlineConfig(config.getId(), configLimit, config.getName(), clonedOffering);
clonedConfig.setInstructionalMethodId(config.getInstructionalMethodId());
clonedConfig.setInstructionalMethodName(config.getInstructionalMethodName());
clonedConfig.setEnrollment(configEnrollment);
configs.put(config, clonedConfig);
for (Iterator<Subpart> f = config.getSubparts().iterator(); f.hasNext(); ) {
Subpart subpart = f.next();
Subpart clonedSubpart = new Subpart(subpart.getId(), subpart.getInstructionalType(), subpart.getName(), clonedConfig, (subpart.getParent() == null ? null : subparts.get(subpart.getParent())));
clonedSubpart.setAllowOverlap(subpart.isAllowOverlap());
clonedSubpart.setCredit(subpart.getCredit());
subparts.put(subpart, clonedSubpart);
for (Iterator<Section> g = subpart.getSections().iterator(); g.hasNext(); ) {
Section section = g.next();
int limit = section.getLimit();
int enrl = section.getEnrollments(assignment()).size();
if (limit >= 0) {
// limited section, deduct enrollments
limit -= section.getEnrollments(assignment()).size();
if (limit < 0)
// over-enrolled, but not unlimited
limit = 0;
if (studentId >= 0)
for (Enrollment enrollment : section.getEnrollments(assignment())) if (enrollment.getStudent().getId() == studentId) {
limit++;
enrl--;
break;
}
}
OnlineSection clonedSection = new OnlineSection(section.getId(), limit, section.getName(course.getId()), clonedSubpart, section.getPlacement(), section.getInstructors(), (section.getParent() == null ? null : sections.get(section.getParent())));
clonedSection.setName(-1l, section.getName(-1l));
clonedSection.setNote(section.getNote());
clonedSection.setSpaceExpected(section.getSpaceExpected());
clonedSection.setSpaceHeld(section.getSpaceHeld());
clonedSection.setEnrollment(enrl);
clonedSection.setCancelled(section.isCancelled());
if (section.getIgnoreConflictWithSectionIds() != null)
for (Long id : section.getIgnoreConflictWithSectionIds()) clonedSection.addIgnoreConflictWith(id);
if (limit > 0) {
double available = Math.round(section.getSpaceExpected() - limit);
clonedSection.setPenalty(available / section.getLimit());
}
sections.put(section, clonedSection);
classTable.put(section.getId(), clonedSection);
}
}
}
if (course.getOffering().hasReservations()) {
for (Reservation reservation : course.getOffering().getReservations()) {
int reservationLimit = (int) Math.round(reservation.getLimit());
if (reservationLimit >= 0) {
reservationLimit -= reservation.getEnrollments(assignment()).size();
if (reservationLimit < 0)
reservationLimit = 0;
for (Iterator<Enrollment> i = reservation.getEnrollments(assignment()).iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getStudent().getId() == studentId) {
reservationLimit++;
break;
}
}
if (reservationLimit <= 0 && !reservation.mustBeUsed())
continue;
}
boolean applicable = originalStudent != null && reservation.isApplicable(originalStudent);
if (reservation instanceof CourseReservation)
applicable = (course.getId() == ((CourseReservation) reservation).getCourse().getId());
if (reservation instanceof org.cpsolver.studentsct.reservation.DummyReservation) {
// the student is already enrolled in the course
for (Enrollment enrollment : course.getEnrollments(assignment())) if (enrollment.getStudent().getId() == studentId) {
applicable = true;
break;
}
}
Reservation clonedReservation = new OnlineReservation(0, reservation.getId(), clonedOffering, reservation.getPriority(), reservation.canAssignOverLimit(), reservationLimit, applicable, reservation.mustBeUsed(), reservation.isAllowOverlap(), reservation.isExpired());
for (Config config : reservation.getConfigs()) clonedReservation.addConfig(configs.get(config));
for (Map.Entry<Subpart, Set<Section>> entry : reservation.getSections().entrySet()) {
Set<Section> clonedSections = new HashSet<Section>();
for (Section section : entry.getValue()) clonedSections.add(sections.get(section));
clonedReservation.getSections().put(subparts.get(entry.getKey()), clonedSections);
}
}
}
return clonedCourse;
}
use of org.cpsolver.studentsct.model.Section 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.Section 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()+")");
}
}
}
}
Aggregations