use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Section method getTotalUnreservedSpaceNoCache.
private double getTotalUnreservedSpaceNoCache() {
// (in which case there is no unreserved space)
if (getLimit() < 0) {
// exclude reservations that are not directly set on this section
for (Reservation r : getSectionReservations()) {
// ignore expired reservations
if (r.isExpired())
continue;
// there is an unlimited reservation -> no unreserved space
if (r.getLimit() < 0)
return 0.0;
}
return Double.MAX_VALUE;
}
// we need to check all reservations linked with this section
double available = getLimit(), reserved = 0, exclusive = 0;
Set<Section> sections = new HashSet<Section>();
reservations: for (Reservation r : getSectionReservations()) {
// ignore expired reservations
if (r.isExpired())
continue;
// unlimited reservation -> no unreserved space
if (r.getLimit() < 0)
return 0.0;
for (Section s : r.getSections(getSubpart())) {
if (s.equals(this))
continue;
if (s.getLimit() < 0)
continue reservations;
if (sections.add(s))
available += s.getLimit();
}
reserved += r.getLimit();
if (r.getSections(getSubpart()).size() == 1)
exclusive += r.getLimit();
}
return Math.min(available - reserved, getLimit() - exclusive);
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class StudentSectioningXMLLoader method loadEnrollment.
/**
* Load enrollment
* @param enrollmentEl enrollment element (current, best, or initial)
* @param request parent request
* @return loaded enrollment
*/
protected Enrollment loadEnrollment(Element enrollmentEl, Request request) {
if (request instanceof CourseRequest) {
CourseRequest courseRequest = (CourseRequest) request;
HashSet<Section> sections = new HashSet<Section>();
for (Iterator<?> k = enrollmentEl.elementIterator("section"); k.hasNext(); ) {
Element sectionEl = (Element) k.next();
Section section = courseRequest.getSection(Long.parseLong(sectionEl.attributeValue("id")));
sections.add(section);
}
Reservation reservation = null;
if (enrollmentEl.attributeValue("reservation", null) != null) {
long reservationId = Long.valueOf(enrollmentEl.attributeValue("reservation"));
for (Course course : courseRequest.getCourses()) for (Reservation r : course.getOffering().getReservations()) if (r.getId() == reservationId) {
reservation = r;
break;
}
}
if (!sections.isEmpty())
return courseRequest.createEnrollment(sections, reservation);
} else if (request instanceof FreeTimeRequest) {
return ((FreeTimeRequest) request).createEnrollment();
}
return null;
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class RequiredReservation method inConflict.
/**
* A given enrollment is conflicting, if there is a reservation that
* the student must use, but the given enrollment does not use it.
*
* @param enrollment {@link Enrollment} that is being considered
* @return true, if the enrollment does not follow a reservation that must be used
*/
@Override
public boolean inConflict(Assignment<Request, Enrollment> assignment, Enrollment enrollment) {
// enrollment's config
Config config = enrollment.getConfig();
// exclude free time requests
if (config == null)
return false;
// no reservations
if (!config.getOffering().hasReservations())
return false;
// enrollment's reservation
Reservation reservation = enrollment.getReservation();
// already has a reservation that must be used
if (reservation != null && reservation.mustBeUsed())
return false;
// if a reservation is required for the student, fail
for (Reservation r : config.getOffering().getReservations()) if (r.mustBeUsed() && r.isApplicable(enrollment.getStudent()))
return true;
return false;
}
use of org.cpsolver.studentsct.reservation.Reservation 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.reservation.Reservation in project cpsolver by UniTime.
the class ReservationLimit method computeConflicts.
/**
* A given enrollment is conflicting, if the reservation's remaining available space
* (computed by {@link Reservation#getReservedAvailableSpace(Assignment, Request)})
* is below the requests weight {@link Request#getWeight()}. <br>
* If the limit is breached, one or more existing enrollments are
* selected as conflicting until there is enough space in the reservation.
* Similarly, if the enrollment does not have the reservation, it is checked
* that there is enough unreserved space in the desired configuration.
*
* @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) {
// enrollment's config
Config config = enrollment.getConfig();
// exclude free time requests
if (config == null)
return;
// no reservations
if (!config.getOffering().hasReservations())
return;
// enrollment's reservation
Reservation reservation = enrollment.getReservation();
// check space in the reservation reservation
if (reservation != null) {
// check reservation too
double reserved = reservation.getReservedAvailableSpace(assignment, enrollment.getRequest());
if (reservation.getLimit() >= 0 && reserved < enrollment.getRequest().getWeight()) {
// reservation is not unlimited and there is not enough space in it
// try to free some space in the reservation
List<Enrollment> adepts = new ArrayList<Enrollment>(config.getEnrollments(assignment).size());
for (Enrollment e : config.getEnrollments(assignment)) {
if (e.getRequest().equals(enrollment.getRequest()))
continue;
if (!reservation.equals(e.getReservation()))
continue;
if (conflicts.contains(e))
reserved += e.getRequest().getWeight();
else
adepts.add(e);
}
while (reserved < enrollment.getRequest().getWeight()) {
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);
reserved += conflict.getRequest().getWeight();
conflicts.add(conflict);
}
}
// if not configuration reservation -> check configuration unavailable space
if (!hasConfigReservation(enrollment)) {
// check reservation can assign over the limit
if (reservation.canBatchAssignOverLimit())
return;
// the section for an enrollment w/o configuration reservation
if (config.getTotalUnreservedSpace() < enrollment.getRequest().getWeight()) {
conflicts.add(enrollment);
return;
}
double unreserved = getUnreservedSpace(assignment, config, enrollment.getRequest(), true);
if (unreserved < 0.0) {
// no unreserved space available -> cannot be assigned
// try to unassign some other enrollments that also do not have config reservation
List<Enrollment> adepts = new ArrayList<Enrollment>(config.getEnrollments(assignment).size());
for (Enrollment e : config.getEnrollments(assignment)) {
if (e.getRequest().equals(enrollment.getRequest()))
continue;
if (hasConfigReservation(e))
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);
}
}
}
} else {
// the section for an enrollment w/o reservation
if (config.getOffering().getTotalUnreservedSpace() < enrollment.getRequest().getWeight() || config.getTotalUnreservedSpace() < enrollment.getRequest().getWeight()) {
conflicts.add(enrollment);
return;
}
// check configuration unavailable space too
double unreserved = getUnreservedSpace(assignment, config, enrollment.getRequest(), false);
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>(config.getEnrollments(assignment).size());
for (Enrollment e : config.getEnrollments(assignment)) {
if (e.getRequest().equals(enrollment.getRequest()))
continue;
if (e.getReservation() != null)
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);
}
}
}
}
Aggregations