use of org.cpsolver.studentsct.model.FreeTimeRequest in project cpsolver by UniTime.
the class TimeOverlapConflictTable method createTable.
/**
* Create report
*
* @param assignment current assignment
* @param includeLastLikeStudents
* true, if last-like students should be included (i.e.,
* {@link Student#isDummy()} is true)
* @param includeRealStudents
* true, if real students should be included (i.e.,
* {@link Student#isDummy()} is false)
* @param useAmPm use 12-hour format
* @return report as comma separated text file
*/
public CSVFile createTable(Assignment<Request, Enrollment> assignment, boolean includeLastLikeStudents, boolean includeRealStudents, boolean useAmPm) {
CSVFile csv = new CSVFile();
csv.setHeader(new CSVFile.CSVField[] { new CSVFile.CSVField("Course"), new CSVFile.CSVField("Total\nConflicts"), new CSVFile.CSVField("Class"), new CSVFile.CSVField("Meeting Time"), new CSVFile.CSVField("Time\nConflicts"), new CSVFile.CSVField("% of Total\nConflicts"), new CSVFile.CSVField("Conflicting\nClass"), new CSVFile.CSVField("Conflicting\nMeeting Time"), new CSVFile.CSVField("Overlap [min]"), new CSVFile.CSVField("Joined\nConflicts"), new CSVFile.CSVField("% of Total\nConflicts") });
Set<Conflict> confs = new HashSet<Conflict>();
for (Request r1 : getModel().variables()) {
Enrollment e1 = assignment.getValue(r1);
if (e1 == null || r1 instanceof FreeTimeRequest)
continue;
for (Request r2 : r1.getStudent().getRequests()) {
Enrollment e2 = assignment.getValue(r2);
if (r2 instanceof FreeTimeRequest) {
FreeTimeRequest ft = (FreeTimeRequest) r2;
confs.addAll(iTOC.conflicts(e1, ft.createEnrollment()));
} else if (e2 != null && r1.getId() < r2.getId()) {
confs.addAll(iTOC.conflicts(e1, e2));
}
}
}
HashMap<Course, Set<Long>> totals = new HashMap<Course, Set<Long>>();
HashMap<CourseSection, Map<CourseSection, Double>> conflictingPairs = new HashMap<CourseSection, Map<CourseSection, Double>>();
HashMap<CourseSection, Set<Long>> sectionOverlaps = new HashMap<CourseSection, Set<Long>>();
for (Conflict conflict : confs) {
if (conflict.getStudent().isDummy() && !includeLastLikeStudents)
continue;
if (!conflict.getStudent().isDummy() && !includeRealStudents)
continue;
if (conflict.getR1() == null || conflict.getR1() instanceof FreeTimeRequest || conflict.getR2() == null || conflict.getR2() instanceof FreeTimeRequest)
continue;
Section s1 = (Section) conflict.getS1(), s2 = (Section) conflict.getS2();
Request r1 = conflict.getR1();
Course c1 = assignment.getValue(conflict.getR1()).getCourse();
Request r2 = conflict.getR2();
Course c2 = assignment.getValue(conflict.getR2()).getCourse();
CourseSection a = new CourseSection(c1, s1);
CourseSection b = new CourseSection(c2, s2);
Set<Long> students = totals.get(c1);
if (students == null) {
students = new HashSet<Long>();
totals.put(c1, students);
}
students.add(r1.getStudent().getId());
students = totals.get(c2);
if (students == null) {
students = new HashSet<Long>();
totals.put(c2, students);
}
students.add(r2.getStudent().getId());
Set<Long> total = sectionOverlaps.get(a);
if (total == null) {
total = new HashSet<Long>();
sectionOverlaps.put(a, total);
}
total.add(r1.getStudent().getId());
Map<CourseSection, Double> pair = conflictingPairs.get(a);
if (pair == null) {
pair = new HashMap<CourseSection, Double>();
conflictingPairs.put(a, pair);
}
Double prev = pair.get(b);
pair.put(b, r2.getWeight() + (prev == null ? 0.0 : prev.doubleValue()));
total = sectionOverlaps.get(b);
if (total == null) {
total = new HashSet<Long>();
sectionOverlaps.put(b, total);
}
total.add(r2.getStudent().getId());
pair = conflictingPairs.get(b);
if (pair == null) {
pair = new HashMap<CourseSection, Double>();
conflictingPairs.put(b, pair);
}
prev = pair.get(a);
pair.put(a, r1.getWeight() + (prev == null ? 0.0 : prev.doubleValue()));
}
Comparator<Course> courseComparator = new Comparator<Course>() {
@Override
public int compare(Course a, Course b) {
int cmp = a.getName().compareTo(b.getName());
if (cmp != 0)
return cmp;
return a.getId() < b.getId() ? -1 : a.getId() == b.getId() ? 0 : 1;
}
};
Comparator<Section> sectionComparator = new Comparator<Section>() {
@Override
public int compare(Section a, Section b) {
int cmp = a.getSubpart().getConfig().getOffering().getName().compareTo(b.getSubpart().getConfig().getOffering().getName());
if (cmp != 0)
return cmp;
cmp = a.getSubpart().getInstructionalType().compareTo(b.getSubpart().getInstructionalType());
// cmp = a.getName().compareTo(b.getName());
if (cmp != 0)
return cmp;
return a.getId() < b.getId() ? -1 : a.getId() == b.getId() ? 0 : 1;
}
};
TreeSet<Course> courses = new TreeSet<Course>(courseComparator);
courses.addAll(totals.keySet());
for (Course course : courses) {
Set<Long> total = totals.get(course);
TreeSet<Section> sections = new TreeSet<Section>(sectionComparator);
for (Map.Entry<CourseSection, Set<Long>> entry : sectionOverlaps.entrySet()) if (course.equals(entry.getKey().getCourse()))
sections.add(entry.getKey().getSection());
boolean firstCourse = true;
for (Section section : sections) {
Set<Long> sectionOverlap = sectionOverlaps.get(new CourseSection(course, section));
Map<CourseSection, Double> pair = conflictingPairs.get(new CourseSection(course, section));
boolean firstClass = true;
for (CourseSection other : new TreeSet<CourseSection>(pair.keySet())) {
List<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>();
line.add(new CSVFile.CSVField(firstCourse && firstClass ? course.getName() : ""));
line.add(new CSVFile.CSVField(firstCourse && firstClass ? total.size() : ""));
line.add(new CSVFile.CSVField(firstClass ? section.getSubpart().getName() + " " + section.getName(course.getId()) : ""));
line.add(new CSVFile.CSVField(firstClass ? section.getTime() == null ? "" : section.getTime().getDayHeader() + " " + section.getTime().getStartTimeHeader(useAmPm) + " - " + section.getTime().getEndTimeHeader(useAmPm) : ""));
line.add(new CSVFile.CSVField(firstClass && sectionOverlap != null ? String.valueOf(sectionOverlap.size()) : ""));
line.add(new CSVFile.CSVField(firstClass && sectionOverlap != null ? sDF2.format(((double) sectionOverlap.size()) / total.size()) : ""));
line.add(new CSVFile.CSVField(other.getCourse().getName() + " " + other.getSection().getSubpart().getName() + " " + other.getSection().getName(other.getCourse().getId())));
line.add(new CSVFile.CSVField(other.getSection().getTime().getDayHeader() + " " + other.getSection().getTime().getStartTimeHeader(useAmPm) + " - " + other.getSection().getTime().getEndTimeHeader(useAmPm)));
line.add(new CSVFile.CSVField(sDF1.format(5 * iTOC.share(section, other.getSection()))));
line.add(new CSVFile.CSVField(sDF1.format(pair.get(other))));
line.add(new CSVFile.CSVField(sDF2.format(pair.get(other) / total.size())));
csv.addLine(line);
firstClass = false;
}
firstCourse = false;
}
csv.addLine();
}
return csv;
}
use of org.cpsolver.studentsct.model.FreeTimeRequest in project cpsolver by UniTime.
the class EqualWeightCriterion method compare.
@Override
public int compare(Assignment<Request, Enrollment> assignment, Enrollment[] current, Enrollment[] best) {
if (best == null)
return -1;
// 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;
for (int idx = 0; idx < current.length; idx++) {
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);
}
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 -1;
if (bestAssignedCourseReq > currentAssignedCourseReq)
return 1;
if (currentAssignedPriority < bestAssignedPriority)
return -1;
if (bestAssignedPriority < currentAssignedPriority)
return 1;
if (currentAssignedAlternativity < bestAssignedAlternativity)
return -1;
if (bestAssignedAlternativity < currentAssignedAlternativity)
return 1;
// 0.5. avoid course 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].getAssignments() != null && best[idx].getRequest() instanceof CourseRequest) {
for (int x = 0; x < idx; x++) {
if (best[x] != null && best[x].getAssignments() != null && best[x].getRequest() instanceof CourseRequest)
bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(best[x], best[idx]);
}
}
if (current[idx] != null && current[idx].getAssignments() != null && current[idx].getRequest() instanceof CourseRequest) {
for (int x = 0; x < idx; x++) {
if (current[x] != null && current[x].getAssignments() != 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 && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
}
}
if (currentTimeOverlaps < bestTimeOverlaps)
return -1;
if (bestTimeOverlaps < currentTimeOverlaps)
return 1;
}
// 1. minimize number of penalties
double bestPenalties = 0, currentPenalties = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
for (Section section : best[idx].getSections()) bestPenalties += getModel().getOverExpected(assignment, section, best[idx].getRequest());
}
if (current[idx] != null && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
for (Section section : current[idx].getSections()) currentPenalties += getModel().getOverExpected(assignment, section, current[idx].getRequest());
}
}
if (currentPenalties < bestPenalties)
return -1;
if (bestPenalties < currentPenalties)
return 1;
// 2. best number of assigned requests (including free time requests)
if (currentAssignedRequests > bestAssignedRequests)
return -1;
if (bestAssignedRequests > currentAssignedRequests)
return 1;
// 3. maximize selection
int bestSelected = 0, currentSelected = 0;
for (int idx = 0; idx < current.length; idx++) {
Set<Section> preferred = getPreferredSections(getRequest(idx));
if (preferred != null && !preferred.isEmpty()) {
if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
for (Section section : best[idx].getSections()) if (preferred.contains(section))
bestSelected++;
}
if (current[idx] != null && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
for (Section section : current[idx].getSections()) if (preferred.contains(section))
currentSelected++;
}
}
}
if (currentSelected > bestSelected)
return -1;
if (bestSelected > currentSelected)
return 1;
// 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 (current[idx] != null && 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 -1;
if (0.3 * bestSelectedConfigs + 0.7 * bestSelectedSections > 0.3 * currentSelectedConfigs + 0.7 * currentSelectedSections)
return 1;
// 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 && best[idx].getAssignments() != null) {
for (int x = 0; x < idx; x++) {
if (best[x] != null && best[x].getAssignments() != 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 && current[idx].getAssignments() != null) {
for (int x = 0; x < idx; x++) {
if (current[x] != null && current[x].getAssignments() != 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 && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
}
}
if (currentTimeOverlaps < bestTimeOverlaps)
return -1;
if (bestTimeOverlaps < currentTimeOverlaps)
return 1;
}
// 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 && best[idx].getAssignments() != null) {
for (int x = 0; x < idx; x++) {
if (best[x] != null && best[x].getAssignments() != null)
bestDistanceConf += getModel().getDistanceConflict().nrConflicts(best[x], best[idx]);
}
}
if (current[idx] != null && current[idx].getAssignments() != null) {
for (int x = 0; x < idx; x++) {
if (current[x] != null && current[x].getAssignments() != null)
currentDistanceConf += getModel().getDistanceConflict().nrConflicts(current[x], current[idx]);
}
}
}
if (currentDistanceConf < bestDistanceConf)
return -1;
if (bestDistanceConf < currentDistanceConf)
return 1;
}
// 6. avoid no-time sections
int bestNoTime = 0, currentNoTime = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null) {
for (Section section : best[idx].getSections()) if (section.getTime() == null)
bestNoTime++;
}
if (current[idx] != null && current[idx].getAssignments() != null) {
for (Section section : current[idx].getSections()) if (section.getTime() == null)
currentNoTime++;
}
}
if (currentNoTime < bestNoTime)
return -1;
if (bestNoTime < currentNoTime)
return 1;
// 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 && best[idx].getAssignments() != 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 && current[idx].getAssignments() != null) {
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 -1;
if (bestUnavailableSizeFraction < currentUnavailableSizeFraction)
return 1;
// 8. average penalty sections
double bestPenalty = 0.0, currentPenalty = 0.0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null && best[idx].getAssignments() != null) {
for (Section section : best[idx].getSections()) bestPenalty += section.getPenalty();
}
if (current[idx] != null && current[idx].getAssignments() != null) {
for (Section section : current[idx].getSections()) currentPenalty += section.getPenalty();
}
}
if (currentPenalty < bestPenalty)
return -1;
if (bestPenalty < currentPenalty)
return 1;
return 0;
}
use of org.cpsolver.studentsct.model.FreeTimeRequest in project cpsolver by UniTime.
the class StudentSectioningXMLLoader method loadFreeTime.
/**
* Load free time request
* @param requestEl request element
* @param student parent student
* @return loaded free time request
*/
public FreeTimeRequest loadFreeTime(Element requestEl, Student student) {
TimeLocation time = new TimeLocation(Integer.parseInt(requestEl.attributeValue("days"), 2), Integer.parseInt(requestEl.attributeValue("start")), Integer.parseInt(requestEl.attributeValue("length")), 0, 0, requestEl.attributeValue("datePattern") == null ? null : Long.valueOf(requestEl.attributeValue("datePattern")), "", createBitSet(requestEl.attributeValue("dates")), 0);
FreeTimeRequest request = new FreeTimeRequest(Long.parseLong(requestEl.attributeValue("id")), Integer.parseInt(requestEl.attributeValue("priority")), "true".equals(requestEl.attributeValue("alternative")), student, time);
if (requestEl.attributeValue("weight") != null)
request.setWeight(Double.parseDouble(requestEl.attributeValue("weight")));
return request;
}
use of org.cpsolver.studentsct.model.FreeTimeRequest 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;
}
Aggregations