use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class CourseRequest method getReservations.
/**
* Get reservations for this course requests
* @param course given course
* @return reservations for this course requests and the given course
*/
public synchronized List<Reservation> getReservations(Course course) {
if (iReservations == null)
iReservations = new HashMap<Course, List<Reservation>>();
List<Reservation> reservations = iReservations.get(course);
if (reservations == null) {
reservations = new ArrayList<Reservation>();
boolean mustBeUsed = false;
for (Reservation r : course.getOffering().getReservations()) {
if (!r.isApplicable(getStudent()))
continue;
if (!mustBeUsed && r.mustBeUsed()) {
reservations.clear();
mustBeUsed = true;
}
if (mustBeUsed && !r.mustBeUsed())
continue;
reservations.add(r);
}
iReservations.put(course, reservations);
}
return reservations;
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class CourseRequest method computeEnrollments.
/**
* Recursive computation of enrollments
*
* @param enrollments
* list of enrollments to be returned
* @param priority
* zero for the course, one for the first alternative, two for the second alternative
* @param penalty
* penalty of the selected sections
* @param course
* selected course
* @param config
* selected configuration
* @param sections
* sections selected so far
* @param idx
* index of the subparts (a section of 0..idx-1 subparts has been
* already selected)
* @param availableOnly
* only use available sections
* @param skipSameTime
* for each possible times, pick only one section
* @param selectedOnly
* select only sections that are selected (
* {@link CourseRequest#isSelected(Section)} is true)
* @param random
* pick sections in a random order (useful when limit is used)
* @param limit
* when above zero, limit the number of selected enrollments to
* this limit
* @param reservations
* list of applicable reservations
*/
private void computeEnrollments(Assignment<Request, Enrollment> assignment, Collection<Enrollment> enrollments, int priority, double penalty, Course course, Config config, HashSet<Section> sections, int idx, boolean availableOnly, boolean skipSameTime, boolean selectedOnly, boolean random, int limit) {
if (limit > 0 && enrollments.size() >= limit)
return;
if (idx == 0) {
// run only once for each configuration
boolean canOverLimit = false;
if (availableOnly) {
for (Reservation r : getReservations(course)) {
if (!r.canBatchAssignOverLimit())
continue;
if (!r.getConfigs().isEmpty() && !r.getConfigs().contains(config))
continue;
if (r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
canOverLimit = true;
break;
}
}
if (!canOverLimit) {
if (availableOnly && config.getLimit() >= 0 && ConfigLimit.getEnrollmentWeight(assignment, config, this) > config.getLimit())
return;
if (availableOnly && course.getLimit() >= 0 && CourseLimit.getEnrollmentWeight(assignment, course, this) > course.getLimit())
return;
if (config.getOffering().hasReservations()) {
boolean hasReservation = false, hasConfigReservation = false, reservationMustBeUsed = false;
for (Reservation r : getReservations(course)) {
if (r.mustBeUsed())
reservationMustBeUsed = true;
if (availableOnly && r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
if (r.getConfigs().isEmpty()) {
hasReservation = true;
} else if (r.getConfigs().contains(config)) {
hasReservation = true;
hasConfigReservation = true;
}
}
if (!hasConfigReservation && config.getTotalUnreservedSpace() < getWeight())
return;
if (!hasReservation && config.getOffering().getTotalUnreservedSpace() < getWeight())
return;
if (availableOnly && !hasReservation && config.getOffering().getUnreservedSpace(assignment, this) < getWeight())
return;
if (availableOnly && !hasConfigReservation && config.getUnreservedSpace(assignment, this) < getWeight())
return;
if (!hasReservation && reservationMustBeUsed)
return;
}
}
}
if (config.getSubparts().size() == idx) {
if (skipSameTime && sSameTimePrecise) {
boolean waitListedOrSelected = false;
if (!getSelectedChoices().isEmpty() || !getWaitlistedChoices().isEmpty()) {
for (Section section : sections) {
if (isWaitlisted(section) || isSelected(section)) {
waitListedOrSelected = true;
break;
}
}
}
if (!waitListedOrSelected) {
for (Enrollment enrollment : enrollments) {
if (sameTimes(enrollment.getSections(), sections))
return;
}
}
}
if (!config.getOffering().hasReservations()) {
enrollments.add(new Enrollment(this, priority, null, config, new HashSet<SctAssignment>(sections), null));
} else {
Enrollment e = new Enrollment(this, priority, null, config, new HashSet<SctAssignment>(sections), null);
boolean mustHaveReservation = config.getOffering().getTotalUnreservedSpace() < getWeight();
boolean mustHaveConfigReservation = config.getTotalUnreservedSpace() < getWeight();
boolean mustHaveSectionReservation = false;
for (Section s : sections) {
if (s.getTotalUnreservedSpace() < getWeight()) {
mustHaveSectionReservation = true;
break;
}
}
boolean canOverLimit = false;
if (availableOnly) {
for (Reservation r : getReservations(course)) {
if (!r.canBatchAssignOverLimit() || !r.isIncluded(e))
continue;
if (r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
enrollments.add(new Enrollment(this, priority, null, config, new HashSet<SctAssignment>(sections), r));
canOverLimit = true;
}
}
if (!canOverLimit) {
boolean reservationMustBeUsed = false;
reservations: for (Reservation r : (availableOnly ? getSortedReservations(assignment, course) : getReservations(course))) {
if (r.mustBeUsed())
reservationMustBeUsed = true;
if (!r.isIncluded(e))
continue;
if (availableOnly && r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
if (mustHaveConfigReservation && r.getConfigs().isEmpty())
continue;
if (mustHaveSectionReservation)
for (Section s : sections) if (r.getSections(s.getSubpart()) == null && s.getTotalUnreservedSpace() < getWeight())
continue reservations;
enrollments.add(new Enrollment(this, priority, null, config, new HashSet<SctAssignment>(sections), r));
// only one available reservation suffice (the best matching one)
if (availableOnly)
return;
}
// a case w/o reservation
if (!(mustHaveReservation || mustHaveConfigReservation || mustHaveSectionReservation) && !(availableOnly && config.getOffering().getUnreservedSpace(assignment, this) < getWeight()) && !reservationMustBeUsed) {
enrollments.add(new Enrollment(this, (getReservations(course).isEmpty() ? 0 : 1) + priority, null, config, new HashSet<SctAssignment>(sections), null));
}
}
}
} else {
Subpart subpart = config.getSubparts().get(idx);
HashSet<TimeLocation> times = (skipSameTime ? new HashSet<TimeLocation>() : null);
List<Section> sectionsThisSubpart = subpart.getSections();
if (skipSameTime) {
sectionsThisSubpart = new ArrayList<Section>(subpart.getSections());
Collections.sort(sectionsThisSubpart, new AssignmentComparator<Section, Request, Enrollment>(assignment));
}
List<Section> matchingSectionsThisSubpart = new ArrayList<Section>(subpart.getSections().size());
boolean hasChildren = !subpart.getChildren().isEmpty();
for (Section section : sectionsThisSubpart) {
if (section.isCancelled())
continue;
if (getInitialAssignment() != null && (getModel() != null && ((StudentSectioningModel) getModel()).getKeepInitialAssignments()) && !getInitialAssignment().getAssignments().contains(section))
continue;
if (section.getParent() != null && !sections.contains(section.getParent()))
continue;
if (section.isOverlapping(sections))
continue;
if (selectedOnly && !isSelected(section))
continue;
if (!getStudent().isAvailable(section)) {
boolean canOverlap = false;
for (Reservation r : getReservations(course)) {
if (!r.isAllowOverlap())
continue;
if (r.getSections(subpart) != null && !r.getSections(subpart).contains(section))
continue;
if (r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
canOverlap = true;
break;
}
if (!canOverlap)
continue;
}
boolean canOverLimit = false;
if (availableOnly) {
for (Reservation r : getReservations(course)) {
if (!r.canBatchAssignOverLimit())
continue;
if (r.getSections(subpart) != null && !r.getSections(subpart).contains(section))
continue;
if (r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
canOverLimit = true;
break;
}
}
if (!canOverLimit) {
if (availableOnly && section.getLimit() >= 0 && SectionLimit.getEnrollmentWeight(assignment, section, this) > section.getLimit())
continue;
if (config.getOffering().hasReservations()) {
boolean hasReservation = false, hasSectionReservation = false, reservationMustBeUsed = false;
for (Reservation r : getReservations(course)) {
if (r.mustBeUsed())
reservationMustBeUsed = true;
if (availableOnly && r.getReservedAvailableSpace(assignment, this) < getWeight())
continue;
if (r.getSections(subpart) == null) {
hasReservation = true;
} else if (r.getSections(subpart).contains(section)) {
hasReservation = true;
hasSectionReservation = true;
}
}
if (!hasSectionReservation && section.getTotalUnreservedSpace() < getWeight())
continue;
if (availableOnly && !hasSectionReservation && section.getUnreservedSpace(assignment, this) < getWeight())
continue;
if (!hasReservation && reservationMustBeUsed)
continue;
}
}
if (skipSameTime && section.getTime() != null && !hasChildren && !times.add(section.getTime()) && !isSelected(section) && !isWaitlisted(section) && (section.getIgnoreConflictWithSectionIds() == null || section.getIgnoreConflictWithSectionIds().isEmpty()))
continue;
matchingSectionsThisSubpart.add(section);
}
if (random || limit > 0) {
sectionsThisSubpart = new ArrayList<Section>(sectionsThisSubpart);
Collections.shuffle(sectionsThisSubpart);
}
int i = 0;
for (Section section : matchingSectionsThisSubpart) {
sections.add(section);
computeEnrollments(assignment, enrollments, priority, penalty + section.getPenalty(), course, config, sections, idx + 1, availableOnly, skipSameTime, selectedOnly, random, limit < 0 ? limit : Math.max(1, limit * (1 + i) / matchingSectionsThisSubpart.size()));
sections.remove(section);
i++;
}
}
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class StudentSectioningXMLLoader method loadReservation.
/**
* Load reservation
* @param reservationEl reservation element
* @param offering parent offering
* @param configTable config table (of the offering)
* @param sectionTable section table (of the offering)
* @return loaded reservation
*/
protected Reservation loadReservation(Element reservationEl, Offering offering, HashMap<Long, Config> configTable, HashMap<Long, Section> sectionTable) {
Reservation r = null;
if ("individual".equals(reservationEl.attributeValue("type"))) {
Set<Long> studentIds = new HashSet<Long>();
for (Iterator<?> k = reservationEl.elementIterator("student"); k.hasNext(); ) {
Element studentEl = (Element) k.next();
studentIds.add(Long.parseLong(studentEl.attributeValue("id")));
}
r = new IndividualReservation(Long.valueOf(reservationEl.attributeValue("id")), offering, studentIds);
} else if ("group".equals(reservationEl.attributeValue("type"))) {
Set<Long> studentIds = new HashSet<Long>();
for (Iterator<?> k = reservationEl.elementIterator("student"); k.hasNext(); ) {
Element studentEl = (Element) k.next();
studentIds.add(Long.parseLong(studentEl.attributeValue("id")));
}
r = new GroupReservation(Long.valueOf(reservationEl.attributeValue("id")), Double.parseDouble(reservationEl.attributeValue("limit", "-1")), offering, studentIds);
} else if ("curriculum".equals(reservationEl.attributeValue("type"))) {
List<String> classifications = new ArrayList<String>();
for (Iterator<?> k = reservationEl.elementIterator("classification"); k.hasNext(); ) {
Element clasfEl = (Element) k.next();
classifications.add(clasfEl.attributeValue("code"));
}
List<String> majors = new ArrayList<String>();
for (Iterator<?> k = reservationEl.elementIterator("major"); k.hasNext(); ) {
Element majorEl = (Element) k.next();
majors.add(majorEl.attributeValue("code"));
}
r = new CurriculumReservation(Long.valueOf(reservationEl.attributeValue("id")), Double.parseDouble(reservationEl.attributeValue("limit", "-1")), offering, reservationEl.attributeValue("area"), classifications, majors);
} else if ("course".equals(reservationEl.attributeValue("type"))) {
long courseId = Long.parseLong(reservationEl.attributeValue("course"));
for (Course course : offering.getCourses()) {
if (course.getId() == courseId)
r = new CourseReservation(Long.valueOf(reservationEl.attributeValue("id")), course);
}
} else if ("dummy".equals(reservationEl.attributeValue("type"))) {
r = new DummyReservation(offering);
} else if ("override".equals(reservationEl.attributeValue("type"))) {
Set<Long> studentIds = new HashSet<Long>();
for (Iterator<?> k = reservationEl.elementIterator("student"); k.hasNext(); ) {
Element studentEl = (Element) k.next();
studentIds.add(Long.parseLong(studentEl.attributeValue("id")));
}
r = new ReservationOverride(Long.valueOf(reservationEl.attributeValue("id")), offering, studentIds);
}
if (r == null) {
sLogger.error("Unknown reservation type " + reservationEl.attributeValue("type"));
return null;
}
r.setExpired("true".equals(reservationEl.attributeValue("expired", "false")));
for (Iterator<?> k = reservationEl.elementIterator("config"); k.hasNext(); ) {
Element configEl = (Element) k.next();
r.addConfig(configTable.get(Long.parseLong(configEl.attributeValue("id"))));
}
for (Iterator<?> k = reservationEl.elementIterator("section"); k.hasNext(); ) {
Element sectionEl = (Element) k.next();
r.addSection(sectionTable.get(Long.parseLong(sectionEl.attributeValue("id"))));
}
r.setPriority(Integer.parseInt(reservationEl.attributeValue("priority", String.valueOf(r.getPriority()))));
r.setMustBeUsed("true".equals(reservationEl.attributeValue("mustBeUsed", r.mustBeUsed() ? "true" : "false")));
r.setAllowOverlap("true".equals(reservationEl.attributeValue("allowOverlap", r.isAllowOverlap() ? "true" : "false")));
r.setCanAssignOverLimit("true".equals(reservationEl.attributeValue("canAssignOverLimit", r.canAssignOverLimit() ? "true" : "false")));
return r;
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Enrollment method guessReservation.
/**
* Guess the reservation based on the enrollment
* @param assignment current assignment
* @param onlyAvailable use only reservation that have some space left in them
*/
public void guessReservation(Assignment<Request, Enrollment> assignment, boolean onlyAvailable) {
if (iCourse != null) {
Reservation best = null;
for (Reservation reservation : ((CourseRequest) iRequest).getReservations(iCourse)) {
if (reservation.isIncluded(this)) {
if (onlyAvailable && reservation.getContext(assignment).getReservedAvailableSpace(assignment, iRequest) < iRequest.getWeight() && !reservation.canBatchAssignOverLimit())
continue;
if (best == null || best.getPriority() > reservation.getPriority()) {
best = reservation;
} else if (best.getPriority() == reservation.getPriority() && best.getContext(assignment).getReservedAvailableSpace(assignment, iRequest) < reservation.getContext(assignment).getReservedAvailableSpace(assignment, iRequest)) {
best = reservation;
}
}
}
iReservation = best;
}
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Offering method getUnreservedSpace.
/**
* Available space in the offering that is not reserved by any reservation
* @param assignment current request
* @param excludeRequest excluding given request (if not null)
* @return remaining unreserved space in the offering
**/
public double getUnreservedSpace(Assignment<Request, Enrollment> assignment, Request excludeRequest) {
// compute available space
double available = 0.0;
for (Config config : getConfigs()) {
available += config.getLimit() - config.getContext(assignment).getEnrollmentWeight(assignment, excludeRequest);
// (in which case there is no unreserved space)
if (config.getLimit() < 0) {
for (Reservation r : getReservations()) {
// 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;
}
}
// compute reserved space (out of the available space)
double reserved = 0;
for (Reservation r : getReservations()) {
// ignore expired reservations
if (r.isExpired())
continue;
// unlimited reservation -> no unreserved space
if (r.getLimit() < 0)
return 0.0;
reserved += Math.max(0.0, r.getContext(assignment).getReservedAvailableSpace(assignment, excludeRequest));
}
return available - reserved;
}
Aggregations