use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class MultiCriteriaBranchAndBoundSelection method isAllowed.
public boolean isAllowed(int idx, Enrollment enrollment) {
if (enrollment.isCourseRequest()) {
CourseRequest request = (CourseRequest) enrollment.getRequest();
if (iRequiredUnassinged != null && iRequiredUnassinged.contains(request))
return false;
Config reqConfig = iRequiredConfig.get(request);
if (reqConfig != null) {
if (!reqConfig.equals(enrollment.getConfig()))
return false;
Hashtable<Subpart, Section> reqSections = iRequiredSection.get(request);
for (Section section : enrollment.getSections()) {
Section reqSection = reqSections.get(section.getSubpart());
if (reqSection == null)
continue;
if (!section.equals(reqSection))
return false;
}
}
} else if (iRequiredFreeTimes.contains(enrollment.getRequest())) {
if (enrollment.getAssignments() == null || enrollment.getAssignments().isEmpty())
return false;
}
return true;
}
use of org.cpsolver.studentsct.model.Subpart 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.getTruePriority() < e2.getTruePriority())
return -1;
if (e1.getTruePriority() > e2.getTruePriority())
return 1;
// 1.5 not available sections
int na1 = 0, na2 = 0;
for (Section section : e1.getSections()) if (section.getLimit() == 0)
na1++;
for (Section section : e2.getSections()) if (section.getLimit() == 0)
na2++;
if (na1 < na2)
return -1;
if (na1 > na2)
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;
}
// 3.9 maximize selection with penalization for not followed reservations
if (e1.getAdjustedPriority() < e2.getAdjustedPriority())
return -1;
if (e1.getAdjustedPriority() > e2.getAdjustedPriority())
return 1;
// 3.95 avoid past sections
int w1 = 0, w2 = 0;
for (Section section : e1.getSections()) {
if (section.isPast())
w1++;
}
for (Section section : e2.getSections()) {
if (section.isPast())
w2++;
}
if (w1 < w2)
return -1;
if (w2 < w1)
return 1;
// 4. avoid time overlaps
if (getTimesToAvoid() == null) {
if (getModel().getStudentQuality() != null) {
int o1 = getModel().getStudentQuality().penalty(StudentQuality.Type.FreeTimeOverlap, e1) + getModel().getStudentQuality().penalty(StudentQuality.Type.Unavailability, e1);
int o2 = getModel().getStudentQuality().penalty(StudentQuality.Type.FreeTimeOverlap, e2) + getModel().getStudentQuality().penalty(StudentQuality.Type.Unavailability, e2);
if (o1 < o2)
return -1;
if (o2 < o1)
return 1;
} else 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.getRequest().getPriority())
o1 += avoid.overlap(s.getTime());
}
}
for (Section s : e2.getSections()) {
if (s.getTime() != null)
for (TimeToAvoid avoid : getTimesToAvoid()) {
if (avoid.priority() > e2.getRequest().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 and online sections (no-time first, online second)
int n1 = 0, n2 = 0;
int o1 = 0, o2 = 0;
for (Section section : e1.getSections()) {
if (!section.hasTime())
n1++;
if (section.isOnline())
o1++;
}
for (Section section : e2.getSections()) {
if (!section.hasTime())
n2++;
if (section.isOnline())
o2++;
}
if (n1 < n2)
return -1;
if (n2 < n1)
return 1;
if (o1 < o2)
return -1;
if (o2 < o1)
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() / e1.getSections().size();
for (Section section : e2.getSections()) x2 += section.getPenalty() / e2.getSections().size();
if (x1 < x2)
return -1;
if (x2 < x1)
return 1;
return 0;
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class AvoidUnbalancedWhenNoExpectations method getOverExpected.
@Override
public double getOverExpected(Assignment<Request, Enrollment> assignment, Section section, Request request) {
Subpart subpart = section.getSubpart();
if (hasExpectations(subpart) && section.getLimit() > 0)
return super.getOverExpected(assignment, section, request);
if (getDisbalance() == null || getDisbalance() < 0.0)
return 0.0;
double enrlConfig = request.getWeight() + getEnrollment(assignment, subpart.getConfig(), request);
int subparts = section.getSubpart().getConfig().getSubparts().size();
int limit = getLimit(section);
double enrl = request.getWeight() + getEnrollment(assignment, section, request);
if (limit > 0) {
// sections have limits -> desired size is section limit x (total
// enrollment / total limit)
double desired = (enrlConfig / getLimit(subpart)) * limit;
if (enrl - desired >= Math.max(1.0, getDisbalance() * limit))
return 1.0 / subparts;
} else if (isBalanceUnlimited()) {
// unlimited sections -> desired size is total enrollment / number
// of sections
double desired = enrlConfig / subpart.getSections().size();
if (enrl - desired >= Math.max(1.0, getDisbalance() * desired))
return 1.0 / subparts;
}
return 0.0;
}
use of org.cpsolver.studentsct.model.Subpart in project cpsolver by UniTime.
the class Reservation method nrChoices.
/**
* Number of choices and number of chaing choices in the given sub enrollment
*/
private int[] nrChoices(Config config, int idx, HashSet<Section> sections, boolean matching, boolean inclusive) {
if (config.getSubparts().size() == idx) {
return new int[] { 1, matching ? 1 : 0 };
} else {
Subpart subpart = config.getSubparts().get(idx);
Set<Section> matchingSections = getSections(subpart);
int choicesThisSubpart = 0;
int matchingChoicesThisSubpart = 0;
for (Section section : subpart.getSections()) {
if (section.getParent() != null && !sections.contains(section.getParent()))
continue;
if (section.isOverlapping(sections))
continue;
sections.add(section);
boolean m = (inclusive ? matching && (matchingSections == null || matchingSections.contains(section)) : matching || (matchingSections != null && matchingSections.contains(section)));
int[] x = nrChoices(config, 1 + idx, sections, m, inclusive);
choicesThisSubpart += x[0];
matchingChoicesThisSubpart += x[1];
sections.remove(section);
}
return new int[] { choicesThisSubpart, matchingChoicesThisSubpart };
}
}
Aggregations