use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class EqualWeightCriterion method canImprove.
@Override
public boolean canImprove(Assignment<Request, Enrollment> assignment, int maxIdx, Enrollment[] current, Enrollment[] best) {
// 0. best number of assigned course requests (including alternativity &
// priority)
int currentAssignedCourseReq = 0, bestAssignedCourseReq = 0;
int currentAssignedRequests = 0, bestAssignedRequests = 0;
int currentAssignedPriority = 0, bestAssignedPriority = 0;
int currentAssignedAlternativity = 0, bestAssignedAlternativity = 0;
int alt = 0;
for (int idx = 0; idx < current.length; idx++) {
if (idx < maxIdx) {
if (current[idx] != null && current[idx].getAssignments() != null) {
currentAssignedRequests++;
if (current[idx].isCourseRequest())
currentAssignedCourseReq++;
currentAssignedPriority += current[idx].getPriority() * current[idx].getPriority();
currentAssignedAlternativity += (current[idx].getRequest().isAlternative() ? 1 : 0);
} else if (!isFreeTime(idx) && !getRequest(idx).isAlternative()) {
alt++;
}
} else {
if (!getRequest(idx).isAlternative()) {
currentAssignedRequests++;
if (!isFreeTime(idx))
currentAssignedCourseReq++;
} else if (alt > 0) {
currentAssignedRequests++;
currentAssignedCourseReq++;
alt--;
currentAssignedAlternativity++;
}
}
if (best[idx] != null && best[idx].getAssignments() != null) {
bestAssignedRequests++;
if (best[idx].isCourseRequest())
bestAssignedCourseReq++;
bestAssignedPriority += best[idx].getPriority() * best[idx].getPriority();
bestAssignedAlternativity += (best[idx].getRequest().isAlternative() ? 1 : 0);
}
}
if (currentAssignedCourseReq > bestAssignedCourseReq)
return true;
if (bestAssignedCourseReq > currentAssignedCourseReq)
return false;
if (currentAssignedPriority < bestAssignedPriority)
return true;
if (bestAssignedPriority < currentAssignedPriority)
return false;
if (currentAssignedAlternativity < bestAssignedAlternativity)
return true;
if (bestAssignedAlternativity < currentAssignedAlternativity)
return false;
// 0.5. avoid course time overlaps & unavailabilities
if (getModel().getTimeOverlaps() != null) {
int bestTimeOverlaps = 0, currentTimeOverlaps = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getRequest() instanceof CourseRequest) {
for (int x = 0; x < idx; x++) {
if (best[x] != null && best[x].getRequest() instanceof CourseRequest)
bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(best[x], best[idx]);
}
}
if (current[idx] != null && idx < maxIdx && current[idx].getRequest() instanceof CourseRequest) {
for (int x = 0; x < idx; x++) {
if (current[x] != null && current[x].getRequest() instanceof CourseRequest)
currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(current[x], current[idx]);
}
}
}
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
bestTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(best[idx]);
}
if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
}
}
if (currentTimeOverlaps < bestTimeOverlaps)
return true;
if (bestTimeOverlaps < currentTimeOverlaps)
return false;
}
// 1. maximize number of penalties
double bestPenalties = 0, currentPenalties = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (Section section : best[idx].getSections()) bestPenalties += getModel().getOverExpected(assignment, section, best[idx].getRequest());
}
if (current[idx] != null && idx < maxIdx) {
for (Section section : current[idx].getSections()) currentPenalties += getModel().getOverExpected(assignment, section, current[idx].getRequest());
}
}
if (currentPenalties < bestPenalties)
return true;
if (bestPenalties < currentPenalties)
return false;
// 2. best number of assigned requests (including free time requests)
if (currentAssignedRequests > bestAssignedRequests)
return true;
if (bestAssignedRequests > currentAssignedRequests)
return false;
// 3. maximize selection
int bestSelected = 0, currentSelected = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].isCourseRequest()) {
Set<Section> preferred = getPreferredSections(best[idx].getRequest());
if (preferred != null && !preferred.isEmpty()) {
for (Section section : best[idx].getSections()) if (preferred.contains(section)) {
if (idx < maxIdx)
bestSelected++;
} else if (idx >= maxIdx)
bestSelected--;
}
}
if (current[idx] != null && idx < maxIdx && current[idx].isCourseRequest()) {
Set<Section> preferred = getPreferredSections(current[idx].getRequest());
if (preferred != null && !preferred.isEmpty()) {
for (Section section : current[idx].getSections()) if (preferred.contains(section))
currentSelected++;
}
}
}
if (currentSelected > bestSelected)
return true;
if (bestSelected > currentSelected)
return false;
// 3.5 maximize preferences
double bestSelectedConfigs = 0, currentSelectedConfigs = 0;
double bestSelectedSections = 0, currentSelectedSections = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
bestSelectedSections += best[idx].percentSelectedSameSection();
bestSelectedConfigs += best[idx].percentSelectedSameConfig();
if (idx >= maxIdx) {
bestSelectedSections -= 1.0;
bestSelectedConfigs -= 1.0;
}
}
if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
currentSelectedSections += current[idx].percentSelectedSameSection();
currentSelectedConfigs += current[idx].percentSelectedSameConfig();
}
}
if (0.3 * currentSelectedConfigs + 0.7 * currentSelectedSections > 0.3 * bestSelectedConfigs + 0.7 * bestSelectedSections)
return true;
if (0.3 * bestSelectedConfigs + 0.7 * bestSelectedSections > 0.3 * currentSelectedConfigs + 0.7 * currentSelectedSections)
return false;
// 4. avoid time overlaps
if (getModel().getTimeOverlaps() != null) {
int bestTimeOverlaps = 0, currentTimeOverlaps = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (int x = 0; x < idx; x++) {
if (best[x] != null)
bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(best[x], best[idx]);
else if (getStudent().getRequests().get(x) instanceof FreeTimeRequest)
bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(((FreeTimeRequest) getStudent().getRequests().get(x)).createEnrollment(), best[idx]);
}
}
if (current[idx] != null && idx < maxIdx) {
for (int x = 0; x < idx; x++) {
if (current[x] != null)
currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(current[x], current[idx]);
else if (getStudent().getRequests().get(x) instanceof FreeTimeRequest)
currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(((FreeTimeRequest) getStudent().getRequests().get(x)).createEnrollment(), current[idx]);
}
}
}
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
bestTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(best[idx]);
}
if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
}
}
if (currentTimeOverlaps < bestTimeOverlaps)
return true;
if (bestTimeOverlaps < currentTimeOverlaps)
return false;
}
// 5. avoid distance conflicts
if (getModel().getDistanceConflict() != null) {
int bestDistanceConf = 0, currentDistanceConf = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (int x = 0; x < idx; x++) {
if (best[x] != null)
bestDistanceConf += getModel().getDistanceConflict().nrConflicts(best[x], best[idx]);
}
}
if (current[idx] != null && idx < maxIdx) {
for (int x = 0; x < idx; x++) {
if (current[x] != null)
currentDistanceConf += getModel().getDistanceConflict().nrConflicts(current[x], current[idx]);
}
}
}
if (currentDistanceConf < bestDistanceConf)
return true;
if (bestDistanceConf < currentDistanceConf)
return false;
}
// 6. avoid no-time sections
int bestNoTime = 0, currentNoTime = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (Section section : best[idx].getSections()) if (section.getTime() == null)
bestNoTime++;
}
if (current[idx] != null && idx < maxIdx) {
for (Section section : current[idx].getSections()) if (section.getTime() == null)
currentNoTime++;
}
}
if (currentNoTime < bestNoTime)
return true;
if (bestNoTime < currentNoTime)
return false;
// 7. balance sections
double bestUnavailableSize = 0.0, currentUnavailableSize = 0.0;
int bestAltSectionsWithLimit = 0, currentAltSectionsWithLimit = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (Section section : best[idx].getSections()) {
Subpart subpart = section.getSubpart();
// skip unlimited and single section subparts
if (subpart.getSections().size() <= 1 || subpart.getLimit() <= 0)
continue;
// average size
double averageSize = ((double) subpart.getLimit()) / subpart.getSections().size();
// section is below average
if (section.getLimit() < averageSize)
bestUnavailableSize += (averageSize - section.getLimit()) / averageSize;
bestAltSectionsWithLimit++;
}
}
if (current[idx] != null && idx < maxIdx) {
for (Section section : current[idx].getSections()) {
Subpart subpart = section.getSubpart();
// skip unlimited and single section subparts
if (subpart.getSections().size() <= 1 || subpart.getLimit() <= 0)
continue;
// average size
double averageSize = ((double) subpart.getLimit()) / subpart.getSections().size();
// section is below average
if (section.getLimit() < averageSize)
currentUnavailableSize += (averageSize - section.getLimit()) / averageSize;
currentAltSectionsWithLimit++;
}
}
}
double bestUnavailableSizeFraction = (bestUnavailableSize > 0 ? bestUnavailableSize / bestAltSectionsWithLimit : 0.0);
double currentUnavailableSizeFraction = (currentUnavailableSize > 0 ? currentUnavailableSize / currentAltSectionsWithLimit : 0.0);
if (currentUnavailableSizeFraction < bestUnavailableSizeFraction)
return true;
if (bestUnavailableSizeFraction < currentUnavailableSizeFraction)
return false;
// 8. average penalty sections
double bestPenalty = 0.0, currentPenalty = 0.0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (Section section : best[idx].getSections()) bestPenalty += section.getPenalty();
if (idx >= maxIdx && best[idx].isCourseRequest())
bestPenalty -= ((CourseRequest) best[idx].getRequest()).getMinPenalty();
}
if (current[idx] != null && idx < maxIdx) {
for (Section section : current[idx].getSections()) currentPenalty += section.getPenalty();
}
}
if (currentPenalty < bestPenalty)
return true;
if (bestPenalty < currentPenalty)
return false;
return true;
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class StudentRequestXml method exportModel.
public static Document exportModel(Assignment<Request, Enrollment> assignment, StudentSectioningModel model) {
Document document = DocumentHelper.createDocument();
Element requestElement = document.addElement("request");
requestElement.addAttribute("campus", model.getProperties().getProperty("Data.Initiative"));
requestElement.addAttribute("year", model.getProperties().getProperty("Data.Year"));
requestElement.addAttribute("term", model.getProperties().getProperty("Data.Term"));
for (Student student : model.getStudents()) {
Element studentElement = requestElement.addElement("student");
studentElement.addAttribute("key", String.valueOf(student.getId()));
Element courseRequestsElement = studentElement.addElement("updateCourseRequests");
courseRequestsElement.addAttribute("commit", "true");
Collections.sort(student.getRequests(), new Comparator<Request>() {
@Override
public int compare(Request r1, Request r2) {
if (r1.isAlternative() != r2.isAlternative()) {
return (r1.isAlternative() ? 1 : -1);
}
return Double.compare(r1.getPriority(), r2.getPriority());
}
});
boolean hasSchedule = false;
for (Request request : student.getRequests()) {
if (assignment.getValue(request) != null)
hasSchedule = true;
if (request instanceof FreeTimeRequest) {
FreeTimeRequest ftReq = (FreeTimeRequest) request;
Element ftReqElement = courseRequestsElement.addElement("freeTime");
requestElement.addAttribute("days", ftReq.getTime().getDayHeader());
int startSlot = ftReq.getTime().getStartSlot();
int startTime = startSlot * Constants.SLOT_LENGTH_MIN + Constants.FIRST_SLOT_TIME_MIN;
ftReqElement.addAttribute("startTime", s2zDF.format(startTime / 60) + s2zDF.format(startTime % 60));
int endTime = startTime + ftReq.getTime().getLength() * Constants.SLOT_LENGTH_MIN - ftReq.getTime().getBreakTime();
ftReqElement.addAttribute("endTime", s2zDF.format(endTime / 60) + s2zDF.format(endTime % 60));
ftReqElement.addAttribute("length", String.valueOf(ftReq.getTime().getLength() * Constants.SLOT_LENGTH_MIN));
} else {
CourseRequest crReq = (CourseRequest) request;
Element crReqElement = courseRequestsElement.addElement("courseOffering");
Course course = crReq.getCourses().get(0);
crReqElement.addAttribute("subjectArea", course.getSubjectArea());
crReqElement.addAttribute("courseNumber", course.getCourseNumber());
crReqElement.addAttribute("waitlist", crReq.isWaitlist() ? "true" : "false");
crReqElement.addAttribute("alternative", crReq.isAlternative() ? "true" : "false");
for (int i = 1; i < crReq.getCourses().size(); i++) {
Course altCourse = crReq.getCourses().get(i);
Element altCourseElement = crReqElement.addElement("alternative");
altCourseElement.addAttribute("subjectArea", altCourse.getSubjectArea());
altCourseElement.addAttribute("courseNumber", altCourse.getCourseNumber());
}
}
}
if (hasSchedule) {
Element requestScheduleElement = studentElement.addElement("requestSchedule");
requestScheduleElement.addAttribute("type", "commit");
for (Request request : student.getRequests()) {
if (request instanceof CourseRequest) {
CourseRequest crReq = (CourseRequest) request;
Enrollment enrollment = assignment.getValue(crReq);
if (enrollment == null)
continue;
Element crReqElement = requestScheduleElement.addElement("courseOffering");
Course course = enrollment.getCourse();
crReqElement.addAttribute("subjectArea", course.getSubjectArea());
crReqElement.addAttribute("courseNumber", course.getCourseNumber());
for (Section section : enrollment.getSections()) {
Element classEl = crReqElement.addElement("class");
classEl.addAttribute("id", section.getSubpart().getInstructionalType());
classEl.addAttribute("assignmentId", String.valueOf(section.getId()));
}
}
}
}
}
return document;
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class StudentSectioningXMLLoader method loadSubpart.
/**
* Load subpart
* @param subpartEl supart element
* @param config parent config
* @param subpartTable subpart table (of the offering)
* @param sectionTable section table (of the offering)
* @param timetable provided timetable
* @return loaded subpart
*/
protected Subpart loadSubpart(Element subpartEl, Config config, Map<Long, Subpart> subpartTable, Map<Long, Section> sectionTable, Map<Long, Placement> timetable) {
Subpart parentSubpart = null;
if (subpartEl.attributeValue("parent") != null)
parentSubpart = subpartTable.get(Long.valueOf(subpartEl.attributeValue("parent")));
Subpart subpart = new Subpart(Long.parseLong(subpartEl.attributeValue("id")), subpartEl.attributeValue("itype"), subpartEl.attributeValue("name", "P" + subpartEl.attributeValue("id")), config, parentSubpart);
subpart.setAllowOverlap("true".equals(subpartEl.attributeValue("allowOverlap", "false")));
subpart.setCredit(subpartEl.attributeValue("credit"));
for (Iterator<?> l = subpartEl.elementIterator("section"); l.hasNext(); ) {
Element sectionEl = (Element) l.next();
Section section = loadSection(sectionEl, subpart, sectionTable, timetable);
sectionTable.put(new Long(section.getId()), section);
}
return subpart;
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class StudentSectioningXMLSaver method saveReservation.
/**
* Save reservation
* @param reservationEl reservation element to be populated
* @param reservation reservation to be saved
*/
protected void saveReservation(Element reservationEl, Reservation reservation) {
reservationEl.addAttribute("id", getId("reservation", reservation.getId()));
reservationEl.addAttribute("expired", reservation.isExpired() ? "true" : "false");
if (reservation instanceof GroupReservation) {
GroupReservation gr = (GroupReservation) reservation;
reservationEl.addAttribute("type", "group");
for (Long studentId : gr.getStudentIds()) reservationEl.addElement("student").addAttribute("id", getId("student", studentId));
if (gr.getReservationLimit() >= 0.0)
reservationEl.addAttribute("limit", String.valueOf(gr.getReservationLimit()));
} else if (reservation instanceof ReservationOverride) {
reservationEl.addAttribute("type", "override");
ReservationOverride o = (ReservationOverride) reservation;
for (Long studentId : o.getStudentIds()) reservationEl.addElement("student").addAttribute("id", getId("student", studentId));
} else if (reservation instanceof IndividualReservation) {
reservationEl.addAttribute("type", "individual");
for (Long studentId : ((IndividualReservation) reservation).getStudentIds()) reservationEl.addElement("student").addAttribute("id", getId("student", studentId));
} else if (reservation instanceof CurriculumReservation) {
reservationEl.addAttribute("type", "curriculum");
CurriculumReservation cr = (CurriculumReservation) reservation;
if (cr.getReservationLimit() >= 0.0)
reservationEl.addAttribute("limit", String.valueOf(cr.getReservationLimit()));
reservationEl.addAttribute("area", cr.getAcademicArea());
for (String clasf : cr.getClassifications()) reservationEl.addElement("classification").addAttribute("code", clasf);
for (String major : cr.getMajors()) reservationEl.addElement("major").addAttribute("code", major);
} else if (reservation instanceof CourseReservation) {
reservationEl.addAttribute("type", "course");
CourseReservation cr = (CourseReservation) reservation;
reservationEl.addAttribute("course", getId("course", cr.getCourse().getId()));
} else if (reservation instanceof DummyReservation) {
reservationEl.addAttribute("type", "dummy");
}
reservationEl.addAttribute("priority", String.valueOf(reservation.getPriority()));
reservationEl.addAttribute("mustBeUsed", reservation.mustBeUsed() ? "true" : "false");
reservationEl.addAttribute("allowOverlap", reservation.isAllowOverlap() ? "true" : "false");
reservationEl.addAttribute("canAssignOverLimit", reservation.canAssignOverLimit() ? "true" : "false");
for (Config config : reservation.getConfigs()) reservationEl.addElement("config").addAttribute("id", getId("config", config.getId()));
for (Map.Entry<Subpart, Set<Section>> entry : reservation.getSections().entrySet()) {
for (Section section : entry.getValue()) {
reservationEl.addElement("section").addAttribute("id", getId("section", section.getId()));
}
}
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class StudentSectioningXMLSaver method saveLinkedSections.
/**
* Save linked sections
* @param root document root
*/
protected void saveLinkedSections(Element root) {
Element constrainstEl = root.addElement("constraints");
for (LinkedSections linkedSections : getModel().getLinkedSections()) {
Element linkEl = constrainstEl.addElement("linked-sections");
linkEl.addAttribute("mustBeUsed", linkedSections.isMustBeUsed() ? "true" : "false");
for (Offering offering : linkedSections.getOfferings()) for (Subpart subpart : linkedSections.getSubparts(offering)) for (Section section : linkedSections.getSections(subpart)) linkEl.addElement("section").addAttribute("offering", getId("offering", offering.getId())).addAttribute("id", getId("section", section.getId()));
}
}
Aggregations