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 SectionLimit method hasSectionReservation.
/**
* True if the enrollment has reservation for this section.
* Everything else is checked in the {@link ReservationLimit} constraint.
**/
private boolean hasSectionReservation(Enrollment enrollment, Section section) {
Reservation reservation = enrollment.getReservation();
if (reservation == null)
return false;
Set<Section> sections = reservation.getSections(section.getSubpart());
return sections != null && sections.contains(section);
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Offering method getTotalUnreservedSpaceNoCache.
private double getTotalUnreservedSpaceNoCache() {
// compute overall available space
double available = 0.0;
for (Config config : getConfigs()) {
available += config.getLimit();
// (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 maximal 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 += r.getLimit();
}
return Math.max(0.0, available - reserved);
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Section method getUnreservedSpace.
/**
* Available space in the section that is not reserved by any section reservation
* @param assignment current assignment
* @param excludeRequest excluding given request (if not null)
* @return unreserved space in this class
**/
public double getUnreservedSpace(Assignment<Request, Enrollment> assignment, Request excludeRequest) {
// (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;
}
double available = getLimit() - getContext(assignment).getEnrollmentWeight(assignment, excludeRequest);
// exclude reservations that are not directly set on this section
for (Reservation r : getSectionReservations()) {
// ignore expired reservations
if (r.isExpired())
continue;
// unlimited reservation -> all the space is reserved
if (r.getLimit() < 0.0)
return 0.0;
// compute space that can be potentially taken by this reservation
double reserved = r.getContext(assignment).getReservedAvailableSpace(assignment, excludeRequest);
// deduct the space from available space
available -= Math.max(0.0, reserved);
}
return available;
}
use of org.cpsolver.studentsct.reservation.Reservation in project cpsolver by UniTime.
the class Test method section.
public boolean section(Student original) {
OnlineSectioningModel model = new TestModel(iModel.getProperties());
model.setOverExpectedCriterion(iModel.getOverExpectedCriterion());
Student student = new Student(original.getId());
Hashtable<CourseRequest, Set<Section>> preferredSectionsForCourse = new Hashtable<CourseRequest, Set<Section>>();
Map<Long, Section> classTable = new HashMap<Long, Section>();
synchronized (iModel) {
for (Request request : original.getRequests()) {
Request clonnedRequest = addRequest(student, original, request, classTable, model);
Enrollment enrollment = assignment().getValue(request);
if (enrollment != null && enrollment.isCourseRequest()) {
Set<Section> sections = new HashSet<Section>();
for (Section section : enrollment.getSections()) sections.add(classTable.get(section.getId()));
preferredSectionsForCourse.put((CourseRequest) clonnedRequest, sections);
}
}
}
model.addStudent(student);
model.setDistanceConflict(new DistanceConflict(iModel.getDistanceConflict().getDistanceMetric(), model.getProperties()));
model.setTimeOverlaps(new TimeOverlapsCounter(null, model.getProperties()));
for (LinkedSections link : iModel.getLinkedSections()) {
List<Section> sections = new ArrayList<Section>();
for (Offering offering : link.getOfferings()) for (Subpart subpart : link.getSubparts(offering)) for (Section section : link.getSections(subpart)) {
Section x = classTable.get(section.getId());
if (x != null)
sections.add(x);
}
if (sections.size() >= 2)
model.addLinkedSections(link.isMustBeUsed(), sections);
}
OnlineSectioningSelection selection = null;
if (model.getProperties().getPropertyBoolean("StudentWeights.MultiCriteria", true)) {
selection = new MultiCriteriaBranchAndBoundSelection(iModel.getProperties());
} else {
selection = new SuggestionSelection(model.getProperties());
}
selection.setModel(model);
selection.setPreferredSections(preferredSectionsForCourse);
selection.setRequiredSections(new Hashtable<CourseRequest, Set<Section>>());
selection.setRequiredFreeTimes(new HashSet<FreeTimeRequest>());
long t0 = JProf.currentTimeMillis();
Assignment<Request, Enrollment> newAssignment = new AssignmentMap<Request, Enrollment>();
BranchBoundNeighbour neighbour = selection.select(newAssignment, student);
long time = JProf.currentTimeMillis() - t0;
inc("[C] CPU Time", time);
if (neighbour == null) {
inc("[F] Failure");
} else {
if (iSuggestions) {
StudentPreferencePenalties penalties = new StudentPreferencePenalties(StudentPreferencePenalties.sDistTypePreference);
double maxOverExpected = 0;
int assigned = 0;
double penalty = 0.0;
Hashtable<CourseRequest, Set<Section>> enrollments = new Hashtable<CourseRequest, Set<Section>>();
List<RequestSectionPair> pairs = new ArrayList<RequestSectionPair>();
for (int i = 0; i < neighbour.getAssignment().length; i++) {
Enrollment enrl = neighbour.getAssignment()[i];
if (enrl != null && enrl.isCourseRequest() && enrl.getAssignments() != null) {
assigned++;
for (Section section : enrl.getSections()) {
maxOverExpected += model.getOverExpected(newAssignment, section, enrl.getRequest());
pairs.add(new RequestSectionPair(enrl.variable(), section));
}
enrollments.put((CourseRequest) enrl.variable(), enrl.getSections());
penalty += penalties.getPenalty(enrl);
}
}
penalty /= assigned;
inc("[S] Initial Penalty", penalty);
double nrSuggestions = 0.0, nrAccepted = 0.0, totalSuggestions = 0.0, nrTries = 0.0;
for (int i = 0; i < pairs.size(); i++) {
RequestSectionPair pair = pairs.get(i);
SuggestionsBranchAndBound suggestionBaB = null;
if (model.getProperties().getPropertyBoolean("StudentWeights.MultiCriteria", true)) {
suggestionBaB = new MultiCriteriaBranchAndBoundSuggestions(model.getProperties(), student, newAssignment, new Hashtable<CourseRequest, Set<Section>>(), new HashSet<FreeTimeRequest>(), enrollments, pair.getRequest(), pair.getSection(), null, maxOverExpected, iModel.getProperties().getPropertyBoolean("StudentWeights.PriorityWeighting", true));
} else {
suggestionBaB = new SuggestionsBranchAndBound(model.getProperties(), student, newAssignment, new Hashtable<CourseRequest, Set<Section>>(), new HashSet<FreeTimeRequest>(), enrollments, pair.getRequest(), pair.getSection(), null, maxOverExpected);
}
long x0 = JProf.currentTimeMillis();
TreeSet<SuggestionsBranchAndBound.Suggestion> suggestions = suggestionBaB.computeSuggestions();
inc("[S] Suggestion CPU Time", JProf.currentTimeMillis() - x0);
totalSuggestions += suggestions.size();
if (!suggestions.isEmpty())
nrSuggestions += 1.0;
nrTries += 1.0;
SuggestionsBranchAndBound.Suggestion best = null;
for (SuggestionsBranchAndBound.Suggestion suggestion : suggestions) {
int a = 0;
double p = 0.0;
for (int j = 0; j < suggestion.getEnrollments().length; j++) {
Enrollment e = suggestion.getEnrollments()[j];
if (e != null && e.isCourseRequest() && e.getAssignments() != null) {
p += penalties.getPenalty(e);
a++;
}
}
p /= a;
if (a > assigned || (assigned == a && p < penalty)) {
best = suggestion;
}
}
if (best != null) {
nrAccepted += 1.0;
Enrollment[] e = best.getEnrollments();
for (int j = 0; j < e.length; j++) if (e[j] != null && e[j].getAssignments() == null)
e[j] = null;
neighbour = new BranchBoundNeighbour(student, best.getValue(), e);
assigned = 0;
penalty = 0.0;
enrollments.clear();
pairs.clear();
for (int j = 0; j < neighbour.getAssignment().length; j++) {
Enrollment enrl = neighbour.getAssignment()[j];
if (enrl != null && enrl.isCourseRequest() && enrl.getAssignments() != null) {
assigned++;
for (Section section : enrl.getSections()) pairs.add(new RequestSectionPair(enrl.variable(), section));
enrollments.put((CourseRequest) enrl.variable(), enrl.getSections());
penalty += penalties.getPenalty(enrl);
}
}
penalty /= assigned;
inc("[S] Improved Penalty", penalty);
}
}
inc("[S] Final Penalty", penalty);
if (nrSuggestions > 0) {
inc("[S] Classes with suggestion", nrSuggestions);
inc("[S] Avg. # of suggestions", totalSuggestions / nrSuggestions);
inc("[S] Suggestion acceptance rate [%]", nrAccepted / nrSuggestions);
} else {
inc("[S] Student with no suggestions available", 1.0);
}
if (!pairs.isEmpty())
inc("[S] Probability that a class has suggestions [%]", nrSuggestions / nrTries);
}
List<Enrollment> enrollments = new ArrayList<Enrollment>();
i: for (int i = 0; i < neighbour.getAssignment().length; i++) {
Request request = original.getRequests().get(i);
Enrollment clonnedEnrollment = neighbour.getAssignment()[i];
if (clonnedEnrollment != null && clonnedEnrollment.getAssignments() != null) {
if (request instanceof FreeTimeRequest) {
enrollments.add(((FreeTimeRequest) request).createEnrollment());
} else {
for (Course course : ((CourseRequest) request).getCourses()) if (course.getId() == clonnedEnrollment.getCourse().getId())
for (Config config : course.getOffering().getConfigs()) if (config.getId() == clonnedEnrollment.getConfig().getId()) {
Set<Section> assignments = new HashSet<Section>();
for (Subpart subpart : config.getSubparts()) for (Section section : subpart.getSections()) {
if (clonnedEnrollment.getSections().contains(section)) {
assignments.add(section);
}
}
Reservation reservation = null;
if (clonnedEnrollment.getReservation() != null) {
for (Reservation r : course.getOffering().getReservations()) if (r.getId() == clonnedEnrollment.getReservation().getId()) {
reservation = r;
break;
}
}
enrollments.add(new Enrollment(request, clonnedEnrollment.getPriority(), course, config, assignments, reservation));
continue i;
}
}
}
}
synchronized (iModel) {
for (Request r : original.getRequests()) {
Enrollment e = assignment().getValue(r);
r.setInitialAssignment(e);
if (e != null)
updateSpace(assignment(), e, true);
}
for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
assignment().unassign(0, r);
boolean fail = false;
for (Enrollment enrl : enrollments) {
if (iModel.conflictValues(assignment(), enrl).isEmpty()) {
assignment().assign(0, enrl);
} else {
fail = true;
break;
}
}
if (fail) {
for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
assignment().unassign(0, r);
for (Request r : original.getRequests()) if (r.getInitialAssignment() != null)
assignment().assign(0, r.getInitialAssignment());
for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
updateSpace(assignment(), assignment().getValue(r), false);
} else {
for (Enrollment enrl : enrollments) updateSpace(assignment(), enrl, false);
}
if (fail)
return false;
}
neighbour.assign(newAssignment, 0);
int a = 0, u = 0, np = 0, zp = 0, pp = 0, cp = 0;
double over = 0;
double p = 0.0;
for (Request r : student.getRequests()) {
if (r instanceof CourseRequest) {
Enrollment e = newAssignment.getValue(r);
if (e != null) {
for (Section s : e.getSections()) {
if (s.getPenalty() < 0.0)
np++;
if (s.getPenalty() == 0.0)
zp++;
if (s.getPenalty() > 0.0)
pp++;
if (s.getLimit() > 0) {
p += s.getPenalty();
cp++;
}
over += model.getOverExpected(newAssignment, s, r);
}
a++;
} else {
u++;
}
}
}
inc("[A] Student");
if (over > 0.0)
inc("[O] Over", over);
if (a > 0)
inc("[A] Assigned", a);
if (u > 0)
inc("[A] Not Assigned", u);
inc("[V] Value", neighbour.value(newAssignment));
if (zp > 0)
inc("[P] Zero penalty", zp);
if (np > 0)
inc("[P] Negative penalty", np);
if (pp > 0)
inc("[P] Positive penalty", pp);
if (cp > 0)
inc("[P] Average penalty", p / cp);
}
inc("[T0] Time <10ms", time < 10 ? 1 : 0);
inc("[T1] Time <100ms", time < 100 ? 1 : 0);
inc("[T2] Time <250ms", time < 250 ? 1 : 0);
inc("[T3] Time <500ms", time < 500 ? 1 : 0);
inc("[T4] Time <1s", time < 1000 ? 1 : 0);
inc("[T5] Time >=1s", time >= 1000 ? 1 : 0);
return true;
}
Aggregations