use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class OnlineSectioningCriterion method compare.
@Override
public int compare(Assignment<Request, Enrollment> assignment, Enrollment e1, Enrollment e2) {
// 1. alternativity
if (e1.getPriority() < e2.getPriority())
return -1;
if (e1.getPriority() > e2.getPriority())
return 1;
// 2. maximize number of penalties
double p1 = 0, p2 = 0;
for (Section section : e1.getSections()) p1 += getModel().getOverExpected(assignment, section, e1.getRequest());
for (Section section : e2.getSections()) p2 += getModel().getOverExpected(assignment, section, e2.getRequest());
if (p1 < p2)
return -1;
if (p2 < p1)
return 1;
// 3. maximize selection
if (e1.isCourseRequest()) {
Set<Section> preferred = getPreferredSections(e1.getRequest());
if (preferred != null && !preferred.isEmpty()) {
int s1 = 0, s2 = 0;
for (Section section : e1.getSections()) if (preferred.contains(section))
s1++;
for (Section section : e2.getSections()) if (preferred.contains(section))
s2++;
if (s2 > s1)
return -1;
if (s1 > s2)
return 1;
}
}
// 3.5 maximize preferences
if (e1.isCourseRequest()) {
double s1 = 0.3 * e1.percentSelectedSameConfig() + 0.7 * e1.percentSelectedSameSection();
double s2 = 0.3 * e2.percentSelectedSameConfig() + 0.7 * e2.percentSelectedSameSection();
if (s1 > s2)
return -1;
if (s2 < s1)
return 1;
}
// 4. avoid time overlaps
if (getTimesToAvoid() == null) {
if (getModel().getTimeOverlaps() != null) {
int o1 = getModel().getTimeOverlaps().nrFreeTimeConflicts(e1) + getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(e1);
int o2 = getModel().getTimeOverlaps().nrFreeTimeConflicts(e2) + getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(e2);
if (o1 < o2)
return -1;
if (o2 < o1)
return 1;
}
} else {
if (e1.getRequest().equals(e2.getRequest()) && e1.isCourseRequest()) {
double o1 = 0.0, o2 = 0.0;
for (Section s : e1.getSections()) {
if (s.getTime() != null)
for (TimeToAvoid avoid : getTimesToAvoid()) {
if (avoid.priority() > e1.getPriority())
o1 += avoid.overlap(s.getTime());
}
}
for (Section s : e2.getSections()) {
if (s.getTime() != null)
for (TimeToAvoid avoid : getTimesToAvoid()) {
if (avoid.priority() > e2.getPriority())
o2 += avoid.overlap(s.getTime());
}
}
if (o1 < o2)
return -1;
if (o2 < o1)
return 1;
}
}
// 5. avoid distance conflicts
if (getModel().getDistanceConflict() != null) {
int c1 = getModel().getDistanceConflict().nrConflicts(e1);
int c2 = getModel().getDistanceConflict().nrConflicts(e2);
if (c1 < c2)
return -1;
if (c2 < c1)
return 1;
}
// 6. avoid no-time sections
int n1 = 0, n2 = 0;
for (Section section : e1.getSections()) if (section.getTime() == null)
n1++;
for (Section section : e2.getSections()) if (section.getTime() == null)
n2++;
if (n1 < n2)
return -1;
if (n2 < n1)
return 1;
// 7. balance sections
double u1 = 0.0, u2 = 0.0;
int a1 = 0, a2 = 0;
for (Section section : e1.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)
u1 += (averageSize - section.getLimit()) / averageSize;
a1++;
}
for (Section section : e2.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)
u2 += (averageSize - section.getLimit()) / averageSize;
a2++;
}
double f1 = (u1 > 0 ? u1 / a1 : 0.0);
double f2 = (u2 > 0 ? u2 / a2 : 0.0);
if (f1 < f2)
return -1;
if (f2 < f1)
return 1;
// 8. average penalty sections
double x1 = 0.0, x2 = 0.0;
for (Section section : e1.getSections()) x1 += section.getPenalty();
for (Section section : e2.getSections()) x2 += section.getPenalty();
if (x1 < x2)
return -1;
if (x2 < x1)
return 1;
return 0;
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class BestPenaltyCriterion method canImprove.
@Override
public boolean canImprove(Assignment<Request, Enrollment> assignment, int maxIdx, Enrollment[] current, Enrollment[] best) {
// 0. best priority & alternativity ignoring free time requests
int alt = 0;
for (int idx = 0; idx < current.length; idx++) {
if (isFreeTime(idx))
continue;
Request request = getRequest(idx);
if (idx < maxIdx) {
if (best[idx] != null) {
if (current[idx] == null)
// higher priority request assigned
return false;
if (best[idx].getPriority() < current[idx].getPriority())
// less alternative request assigned
return false;
if (request.isAlternative())
alt--;
} else {
if (current[idx] != null)
// higher priority request assigned
return true;
if (!request.isAlternative())
alt++;
}
} else {
if (best[idx] != null) {
if (best[idx].getPriority() > 0)
// alternativity can be improved
return true;
} else {
if (!request.isAlternative() || alt > 0)
// priority can be improved
return true;
}
}
}
// 1. maximize number of penalties
int bestPenalties = 0, currentPenalties = 0;
for (int idx = 0; idx < current.length; idx++) {
if (best[idx] != null) {
for (Section section : best[idx].getSections()) bestPenalties += iModel.getOverExpected(assignment, section, best[idx].getRequest());
}
if (current[idx] != null && idx < maxIdx) {
for (Section section : current[idx].getSections()) currentPenalties += iModel.getOverExpected(assignment, section, current[idx].getRequest());
}
}
if (currentPenalties < bestPenalties)
return true;
if (bestPenalties < currentPenalties)
return false;
return false;
}
use of org.cpsolver.studentsct.model.Section 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.Section in project cpsolver by UniTime.
the class CourseLimitCheck method check.
/**
* Check for courses where the limit is below the number of students that
* request the course
*
* @return false, if there is such a case
*/
public boolean check() {
sLog.info("Checking for course limits...");
boolean ret = true;
for (Offering offering : getModel().getOfferings()) {
boolean hasUnlimitedSection = false;
if (iFixUnlimited)
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
if (section.getLimit() < 0)
hasUnlimitedSection = true;
}
}
}
int offeringLimit = 0;
int nrStudents = 0;
for (Course course : offering.getCourses()) {
if (course.getLimit() < 0) {
offeringLimit = -1;
continue;
}
if (iFixUnlimited && hasUnlimitedSection) {
sLog.info("Course " + course + " made unlimited.");
course.setLimit(-1);
offeringLimit = -1;
continue;
}
double total = 0;
double lastLike = 0, real = 0;
for (Request request : getModel().variables()) {
if (request instanceof CourseRequest && ((CourseRequest) request).getCourses().contains(course)) {
total += request.getWeight();
if (request.getStudent().isDummy())
lastLike += request.getWeight();
else
real += request.getWeight();
}
}
nrStudents += Math.round(total);
offeringLimit += course.getLimit();
if (Math.round(total) > course.getLimit()) {
sLog.error("Course " + course + " is requested by " + sDF.format(total) + " students, but its limit is only " + course.getLimit());
ret = false;
iCSVFile.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(course.getName()), new CSVFile.CSVField(course.getLimit()), new CSVFile.CSVField(total), new CSVFile.CSVField(real), new CSVFile.CSVField(lastLike) });
if (iUpZeroLimits && course.getLimit() == 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
} else if (iUpNonZeroLimits && course.getLimit() > 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
}
}
}
if (iUpZeroLimits && offeringLimit == 0 && nrStudents > 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(nrStudents / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && offeringLimit >= 0 && nrStudents > offeringLimit) {
double fact = ((double) nrStudents) / offeringLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
if (offeringLimit >= 0) {
int totalSectionLimit = 0;
for (Config config : offering.getConfigs()) {
int configLimit = -1;
for (Subpart subpart : config.getSubparts()) {
int subpartLimit = 0;
for (Section section : subpart.getSections()) {
subpartLimit += section.getLimit();
}
if (configLimit < 0)
configLimit = subpartLimit;
else
configLimit = Math.min(configLimit, subpartLimit);
}
totalSectionLimit += configLimit;
}
if (totalSectionLimit < offeringLimit) {
sLog.error("Offering limit of " + offering + " is " + offeringLimit + ", but total section limit is only " + totalSectionLimit);
if (iUpZeroLimits && totalSectionLimit == 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(((double) offeringLimit) / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && totalSectionLimit > 0) {
double fact = ((double) offeringLimit) / totalSectionLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
}
}
}
return ret;
}
use of org.cpsolver.studentsct.model.Section in project cpsolver by UniTime.
the class StudentSectioningModel method getExtendedInfo.
/**
* Model extended info. Some more information (that is more expensive to
* compute) is added to an ordinary {@link Model#getInfo(Assignment)}.
*/
@Override
public Map<String, String> getExtendedInfo(Assignment<Request, Enrollment> assignment) {
Map<String, String> info = getInfo(assignment);
/*
int nrLastLikeStudents = getNrLastLikeStudents(true);
if (nrLastLikeStudents != 0 && nrLastLikeStudents != getStudents().size()) {
int nrRealStudents = getStudents().size() - nrLastLikeStudents;
int nrLastLikeCompleteStudents = getNrCompleteLastLikeStudents(true);
int nrRealCompleteStudents = getCompleteStudents().size() - nrLastLikeCompleteStudents;
info.put("Projected students with complete schedule", sDecimalFormat.format(100.0
* nrLastLikeCompleteStudents / nrLastLikeStudents)
+ "% (" + nrLastLikeCompleteStudents + "/" + nrLastLikeStudents + ")");
info.put("Real students with complete schedule", sDecimalFormat.format(100.0 * nrRealCompleteStudents
/ nrRealStudents)
+ "% (" + nrRealCompleteStudents + "/" + nrRealStudents + ")");
int nrLastLikeRequests = getNrLastLikeRequests(true);
int nrRealRequests = variables().size() - nrLastLikeRequests;
int nrLastLikeAssignedRequests = getNrAssignedLastLikeRequests(true);
int nrRealAssignedRequests = assignedVariables().size() - nrLastLikeAssignedRequests;
info.put("Projected assigned requests", sDecimalFormat.format(100.0 * nrLastLikeAssignedRequests
/ nrLastLikeRequests)
+ "% (" + nrLastLikeAssignedRequests + "/" + nrLastLikeRequests + ")");
info.put("Real assigned requests", sDecimalFormat.format(100.0 * nrRealAssignedRequests / nrRealRequests)
+ "% (" + nrRealAssignedRequests + "/" + nrRealRequests + ")");
}
*/
// info.put("Average unassigned priority", sDecimalFormat.format(avgUnassignPriority()));
// info.put("Average number of requests", sDecimalFormat.format(avgNrRequests()));
/*
double total = 0;
for (Request r: variables())
if (r.getAssignment() != null)
total += r.getWeight() * iStudentWeights.getWeight(r.getAssignment());
*/
double dc = 0;
if (getDistanceConflict() != null && getDistanceConflict().getTotalNrConflicts(assignment) != 0) {
Set<DistanceConflict.Conflict> conf = getDistanceConflict().getAllConflicts(assignment);
for (DistanceConflict.Conflict c : conf) dc += avg(c.getR1().getWeight(), c.getR2().getWeight()) * iStudentWeights.getDistanceConflictWeight(assignment, c);
if (!conf.isEmpty())
info.put("Student distance conflicts", conf.size() + " (weighted: " + sDecimalFormat.format(dc) + ")");
}
double toc = 0;
if (getTimeOverlaps() != null && getTimeOverlaps().getTotalNrConflicts(assignment) != 0) {
Set<TimeOverlapsCounter.Conflict> conf = getTimeOverlaps().getAllConflicts(assignment);
int share = 0;
for (TimeOverlapsCounter.Conflict c : conf) {
if (c.getR1() != null)
toc += c.getR1Weight() * iStudentWeights.getTimeOverlapConflictWeight(assignment, c.getE1(), c);
if (c.getR2() != null)
toc += c.getR2Weight() * iStudentWeights.getTimeOverlapConflictWeight(assignment, c.getE2(), c);
share += c.getShare();
}
if (toc != 0.0)
info.put("Time overlapping conflicts", share + " (average: " + sDecimalFormat.format(5.0 * share / getStudents().size()) + " min, weighted: " + sDoubleFormat.format(toc) + ")");
}
/*
info.put("Overall solution value", sDecimalFormat.format(total - dc - toc) + (dc == 0.0 && toc == 0.0 ? "" :
" (" + (dc != 0.0 ? "distance: " + sDecimalFormat.format(dc): "") + (dc != 0.0 && toc != 0.0 ? ", " : "") +
(toc != 0.0 ? "overlap: " + sDecimalFormat.format(toc) : "") + ")")
);
*/
double disbWeight = 0;
int disbSections = 0;
int disb10Sections = 0;
int disb10Limit = getProperties().getPropertyInt("Info.ListDisbalancedSections", 0);
Set<String> disb10SectionList = (disb10Limit == 0 ? null : new TreeSet<String>());
for (Offering offering : getOfferings()) {
for (Config config : offering.getConfigs()) {
double enrl = config.getEnrollmentTotalWeight(assignment, null);
for (Subpart subpart : config.getSubparts()) {
if (subpart.getSections().size() <= 1)
continue;
if (subpart.getLimit() > 0) {
// sections have limits -> desired size is section limit x (total enrollment / total limit)
double ratio = enrl / subpart.getLimit();
for (Section section : subpart.getSections()) {
double desired = ratio * section.getLimit();
disbWeight += Math.abs(section.getEnrollmentTotalWeight(assignment, null) - desired);
disbSections++;
if (Math.abs(desired - section.getEnrollmentTotalWeight(assignment, null)) >= Math.max(1.0, 0.1 * section.getLimit())) {
disb10Sections++;
if (disb10SectionList != null)
disb10SectionList.add(section.getSubpart().getConfig().getOffering().getName() + " " + section.getSubpart().getName() + " " + section.getName());
}
}
} else {
// unlimited sections -> desired size is total enrollment / number of sections
for (Section section : subpart.getSections()) {
double desired = enrl / subpart.getSections().size();
disbWeight += Math.abs(section.getEnrollmentTotalWeight(assignment, null) - desired);
disbSections++;
if (Math.abs(desired - section.getEnrollmentTotalWeight(assignment, null)) >= Math.max(1.0, 0.1 * desired)) {
disb10Sections++;
if (disb10SectionList != null)
disb10SectionList.add(section.getSubpart().getConfig().getOffering().getName() + " " + section.getSubpart().getName() + " " + section.getName());
}
}
}
}
}
}
if (disbSections != 0) {
double assignedCRWeight = getContext(assignment).getAssignedCourseRequestWeight();
info.put("Average disbalance", sDecimalFormat.format(disbWeight / disbSections) + " (" + sDecimalFormat.format(assignedCRWeight == 0 ? 0.0 : 100.0 * disbWeight / assignedCRWeight) + "%)");
String list = "";
if (disb10SectionList != null) {
int i = 0;
for (String section : disb10SectionList) {
if (i == disb10Limit) {
list += "<br>...";
break;
}
list += "<br>" + section;
i++;
}
}
info.put("Sections disbalanced by 10% or more", disb10Sections + " (" + sDecimalFormat.format(disbSections == 0 ? 0.0 : 100.0 * disb10Sections / disbSections) + "%)" + list);
}
return info;
}
Aggregations