Search in sources :

Example 46 with Section

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;
}
Also used : Subpart(org.cpsolver.studentsct.model.Subpart) Section(org.cpsolver.studentsct.model.Section)

Example 47 with Section

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;
}
Also used : FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Section(org.cpsolver.studentsct.model.Section)

Example 48 with Section

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;
}
Also used : FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Subpart(org.cpsolver.studentsct.model.Subpart) Section(org.cpsolver.studentsct.model.Section)

Example 49 with Section

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;
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) CSVFile(org.cpsolver.ifs.util.CSVFile) Config(org.cpsolver.studentsct.model.Config) Subpart(org.cpsolver.studentsct.model.Subpart) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Request(org.cpsolver.studentsct.model.Request) Course(org.cpsolver.studentsct.model.Course) Offering(org.cpsolver.studentsct.model.Offering) Section(org.cpsolver.studentsct.model.Section)

Example 50 with Section

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;
}
Also used : Config(org.cpsolver.studentsct.model.Config) DistanceConflict(org.cpsolver.studentsct.extension.DistanceConflict) Offering(org.cpsolver.studentsct.model.Offering) Section(org.cpsolver.studentsct.model.Section) Constraint(org.cpsolver.ifs.model.Constraint) TimeOverlapsCounter(org.cpsolver.studentsct.extension.TimeOverlapsCounter) StudentConflict(org.cpsolver.studentsct.constraint.StudentConflict) DistanceConflict(org.cpsolver.studentsct.extension.DistanceConflict) TreeSet(java.util.TreeSet) Subpart(org.cpsolver.studentsct.model.Subpart)

Aggregations

Section (org.cpsolver.studentsct.model.Section)59 Subpart (org.cpsolver.studentsct.model.Subpart)34 CourseRequest (org.cpsolver.studentsct.model.CourseRequest)32 Config (org.cpsolver.studentsct.model.Config)23 Request (org.cpsolver.studentsct.model.Request)22 Course (org.cpsolver.studentsct.model.Course)19 Enrollment (org.cpsolver.studentsct.model.Enrollment)19 Offering (org.cpsolver.studentsct.model.Offering)17 HashSet (java.util.HashSet)14 FreeTimeRequest (org.cpsolver.studentsct.model.FreeTimeRequest)14 ArrayList (java.util.ArrayList)13 Set (java.util.Set)11 TreeSet (java.util.TreeSet)10 HashMap (java.util.HashMap)9 Map (java.util.Map)9 Element (org.dom4j.Element)9 Student (org.cpsolver.studentsct.model.Student)7 CSVFile (org.cpsolver.ifs.util.CSVFile)6 DistanceConflict (org.cpsolver.studentsct.extension.DistanceConflict)6 RoomLocation (org.cpsolver.coursett.model.RoomLocation)5