Search in sources :

Example 26 with CourseRequest

use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.

the class CourseConflictTable 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
 */
@SuppressWarnings("unchecked")
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("UnasgnCrs"), new CSVFile.CSVField("ConflCrs"), new CSVFile.CSVField("NrStud"), new CSVFile.CSVField("StudWeight"), new CSVFile.CSVField("NoAlt"), new CSVFile.CSVField("Reason") });
    HashMap<Course, HashMap<Course, Object[]>> unassignedCourseTable = new HashMap<Course, HashMap<Course, Object[]>>();
    for (Request request : new ArrayList<Request>(getModel().unassignedVariables(assignment))) {
        if (request.getStudent().isDummy() && !includeLastLikeStudents)
            continue;
        if (!request.getStudent().isDummy() && !includeRealStudents)
            continue;
        if (request instanceof CourseRequest) {
            CourseRequest courseRequest = (CourseRequest) request;
            if (courseRequest.getStudent().isComplete(assignment))
                continue;
            List<Enrollment> values = courseRequest.values(assignment);
            SectionLimit limitConstraint = null;
            for (GlobalConstraint<Request, Enrollment> c : getModel().globalConstraints()) {
                if (c instanceof SectionLimit) {
                    limitConstraint = (SectionLimit) c;
                    break;
                }
            }
            if (limitConstraint == null) {
                limitConstraint = new SectionLimit(new DataProperties());
                limitConstraint.setModel(getModel());
            }
            List<Enrollment> availableValues = new ArrayList<Enrollment>(values.size());
            for (Enrollment enrollment : values) {
                if (!limitConstraint.inConflict(assignment, enrollment))
                    availableValues.add(enrollment);
            }
            if (availableValues.isEmpty()) {
                Course course = courseRequest.getCourses().get(0);
                HashMap<Course, Object[]> conflictCourseTable = unassignedCourseTable.get(course);
                if (conflictCourseTable == null) {
                    conflictCourseTable = new HashMap<Course, Object[]>();
                    unassignedCourseTable.put(course, conflictCourseTable);
                }
                Object[] weight = conflictCourseTable.get(course);
                double nrStud = (weight == null ? 0.0 : ((Double) weight[0]).doubleValue()) + 1.0;
                double nrStudW = (weight == null ? 0.0 : ((Double) weight[1]).doubleValue()) + request.getWeight();
                boolean noAlt = (weight == null ? true : ((Boolean) weight[2]).booleanValue());
                HashSet<String> expl = (weight == null ? new HashSet<String>() : (HashSet<String>) weight[3]);
                expl.add(course.getName() + " n/a");
                conflictCourseTable.put(course, new Object[] { Double.valueOf(nrStud), Double.valueOf(nrStudW), Boolean.valueOf(noAlt), expl });
            }
            for (Enrollment enrollment : availableValues) {
                Set<Enrollment> conflicts = getModel().conflictValues(assignment, enrollment);
                if (conflicts.isEmpty()) {
                    sLog.warn("Request " + courseRequest + " of student " + courseRequest.getStudent() + " not assigned, however, no conflicts were returned.");
                    assignment.assign(0, enrollment);
                    break;
                }
                Course course = null;
                for (Course c : courseRequest.getCourses()) {
                    if (c.getOffering().equals(enrollment.getConfig().getOffering())) {
                        course = c;
                        break;
                    }
                }
                if (course == null) {
                    sLog.warn("Course not found for request " + courseRequest + " of student " + courseRequest.getStudent() + ".");
                    continue;
                }
                HashMap<Course, Object[]> conflictCourseTable = unassignedCourseTable.get(course);
                if (conflictCourseTable == null) {
                    conflictCourseTable = new HashMap<Course, Object[]>();
                    unassignedCourseTable.put(course, conflictCourseTable);
                }
                for (Enrollment conflict : conflicts) {
                    if (conflict.variable() instanceof CourseRequest) {
                        CourseRequest conflictCourseRequest = (CourseRequest) conflict.variable();
                        Course conflictCourse = null;
                        for (Course c : conflictCourseRequest.getCourses()) {
                            if (c.getOffering().equals(conflict.getConfig().getOffering())) {
                                conflictCourse = c;
                                break;
                            }
                        }
                        if (conflictCourse == null) {
                            sLog.warn("Course not found for request " + conflictCourseRequest + " of student " + conflictCourseRequest.getStudent() + ".");
                            continue;
                        }
                        double weightThisConflict = request.getWeight() / availableValues.size() / conflicts.size();
                        double partThisConflict = 1.0 / availableValues.size() / conflicts.size();
                        Object[] weight = conflictCourseTable.get(conflictCourse);
                        double nrStud = (weight == null ? 0.0 : ((Double) weight[0]).doubleValue()) + partThisConflict;
                        double nrStudW = (weight == null ? 0.0 : ((Double) weight[1]).doubleValue()) + weightThisConflict;
                        boolean noAlt = (weight == null ? areInHardConfict(assignment, request, conflict.getRequest()) : ((Boolean) weight[2]).booleanValue());
                        HashSet<String> expl = (weight == null ? new HashSet<String>() : (HashSet<String>) weight[3]);
                        expl.addAll(explanations(assignment, enrollment, conflict, useAmPm));
                        conflictCourseTable.put(conflictCourse, new Object[] { Double.valueOf(nrStud), Double.valueOf(nrStudW), Boolean.valueOf(noAlt), expl });
                    }
                }
            }
        }
    }
    for (Map.Entry<Course, HashMap<Course, Object[]>> entry : unassignedCourseTable.entrySet()) {
        Course unassignedCourse = entry.getKey();
        HashMap<Course, Object[]> conflictCourseTable = entry.getValue();
        for (Map.Entry<Course, Object[]> entry2 : conflictCourseTable.entrySet()) {
            Course conflictCourse = entry2.getKey();
            Object[] weight = entry2.getValue();
            HashSet<String> expl = (HashSet<String>) weight[3];
            String explStr = "";
            for (Iterator<String> k = new TreeSet<String>(expl).iterator(); k.hasNext(); ) explStr += k.next() + (k.hasNext() ? "\n" : "");
            csv.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(unassignedCourse.getName()), new CSVFile.CSVField(conflictCourse.getName()), new CSVFile.CSVField(sDF.format(weight[0])), new CSVFile.CSVField(sDF.format(weight[1])), new CSVFile.CSVField(((Boolean) weight[2]).booleanValue() ? "Y" : "N"), new CSVFile.CSVField(explStr) });
        }
    }
    if (csv.getLines() != null)
        Collections.sort(csv.getLines(), new Comparator<CSVFile.CSVLine>() {

            @Override
            public int compare(CSVFile.CSVLine l1, CSVFile.CSVLine l2) {
                // int cmp =
                // l2.getField(3).toString().compareTo(l1.getField(3).toString());
                // if (cmp!=0) return cmp;
                int cmp = Double.compare(l2.getField(2).toDouble(), l1.getField(2).toDouble());
                if (cmp != 0)
                    return cmp;
                cmp = l1.getField(0).toString().compareTo(l2.getField(0).toString());
                if (cmp != 0)
                    return cmp;
                return l1.getField(1).toString().compareTo(l2.getField(1).toString());
            }
        });
    return csv;
}
Also used : CSVFile(org.cpsolver.ifs.util.CSVFile) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DataProperties(org.cpsolver.ifs.util.DataProperties) Comparator(java.util.Comparator) Enrollment(org.cpsolver.studentsct.model.Enrollment) Course(org.cpsolver.studentsct.model.Course) HashSet(java.util.HashSet) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) SectionLimit(org.cpsolver.studentsct.constraint.SectionLimit) HashMap(java.util.HashMap) Map(java.util.Map)

Example 27 with CourseRequest

use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.

the class MultiCriteriaBranchAndBoundSelection method canAssign.

/**
 * True if the given request can be assigned
 */
public boolean canAssign(Request request, int idx) {
    if (iCurrentAssignment[idx] != null)
        return true;
    int alt = 0;
    int i = 0;
    float credit = 0;
    for (Iterator<Request> e = iStudent.getRequests().iterator(); e.hasNext(); i++) {
        Request r = e.next();
        if (r.equals(request))
            credit += r.getMinCredit();
        else if (iCurrentAssignment[i] != null)
            credit += iCurrentAssignment[i].getCredit();
        if (r.equals(request))
            continue;
        if (r.isAlternative()) {
            if (iCurrentAssignment[i] != null || (r instanceof CourseRequest && ((CourseRequest) r).isWaitlist()))
                alt--;
        } else {
            if (r instanceof CourseRequest && !((CourseRequest) r).isWaitlist() && iCurrentAssignment[i] == null)
                alt++;
        }
    }
    return (!request.isAlternative() || alt > 0) && (credit <= request.getStudent().getMaxCredit());
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 28 with CourseRequest

use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.

the class MultiCriteriaBranchAndBoundSelection method select.

/**
 * Execute branch & bound, return the best found schedule for the selected
 * student.
 */
public BranchBoundNeighbour select() {
    iT0 = JProf.currentTimeMillis();
    iTimeoutReached = false;
    iCurrentAssignment = new Enrollment[iStudent.getRequests().size()];
    iBestAssignment = null;
    int i = 0;
    for (Request r : iStudent.getRequests()) iCurrentAssignment[i++] = iAssignment.getValue(r);
    saveBest();
    for (int j = 0; j < iCurrentAssignment.length; j++) iCurrentAssignment[j] = null;
    iValues = new HashMap<CourseRequest, List<Enrollment>>();
    backTrack(0);
    iT1 = JProf.currentTimeMillis();
    if (iBestAssignment == null)
        return null;
    return new BranchBoundNeighbour(iStudent, iComparator.getTotalWeight(iAssignment, iBestAssignment), iBestAssignment);
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) BranchBoundNeighbour(org.cpsolver.studentsct.heuristics.selection.BranchBoundSelection.BranchBoundNeighbour) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) ArrayList(java.util.ArrayList) List(java.util.List) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 29 with CourseRequest

use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.

the class OnlineSectioningCriterion method compare.

@Override
public int compare(Assignment<Request, Enrollment> assignment, Enrollment[] current, Enrollment[] best) {
    if (best == null)
        return -1;
    // 0. best priority & alternativity ignoring free time requests
    boolean ft = false;
    boolean res = false;
    for (int idx = 0; idx < current.length; idx++) {
        if (isFreeTime(idx)) {
            ft = true;
            continue;
        }
        Request request = getRequest(idx);
        if (request instanceof CourseRequest && ((CourseRequest) request).hasReservations())
            res = true;
        if (best[idx] != null && best[idx].getAssignments() != null) {
            if (current[idx] == null || current[idx].getSections() == null)
                // higher priority request assigned
                return 1;
            if (best[idx].getTruePriority() < current[idx].getTruePriority())
                // less alternative request assigned
                return 1;
            if (best[idx].getTruePriority() > current[idx].getTruePriority())
                // less alternative request assigned
                return -1;
        } else {
            if (current[idx] != null && current[idx].getAssignments() != null)
                // higher priority request assigned
                return -1;
        }
    }
    // 0.1. allowed, but not available sections
    int bestNotAvailable = 0, currentNotAvailable = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null && best[idx].getAssignments() != null && best[idx].getRequest() instanceof CourseRequest && best[idx].getReservation() != null && best[idx].getReservation().canAssignOverLimit()) {
            for (Section section : best[idx].getSections()) {
                if (section.getLimit() == 0)
                    bestNotAvailable++;
            }
        }
        if (current[idx] != null && current[idx].getAssignments() != null && current[idx].getRequest() instanceof CourseRequest && current[idx].getReservation() != null && current[idx].getReservation().canAssignOverLimit()) {
            for (Section section : current[idx].getSections()) {
                if (section.getLimit() == 0)
                    currentNotAvailable++;
            }
        }
    }
    if (bestNotAvailable > currentNotAvailable)
        return -1;
    if (bestNotAvailable < currentNotAvailable)
        return 1;
    // 0.5. avoid course time overlaps & unavailabilities
    if (getModel().getStudentQuality() != 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().getStudentQuality().penalty(StudentQuality.Type.CourseTimeOverlap, 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().getStudentQuality().penalty(StudentQuality.Type.CourseTimeOverlap, 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().getStudentQuality().penalty(StudentQuality.Type.Unavailability, best[idx]);
            }
            if (current[idx] != null && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
                currentTimeOverlaps += getModel().getStudentQuality().penalty(StudentQuality.Type.Unavailability, current[idx]);
            }
        }
        if (currentTimeOverlaps < bestTimeOverlaps)
            return -1;
        if (bestTimeOverlaps < currentTimeOverlaps)
            return 1;
    } else 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]);
                }
                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, best, idx, section, best[idx].getRequest());
            for (Section section : current[idx].getSections()) currentPenalties += getModel().getOverExpected(assignment, current, idx, section, current[idx].getRequest());
        }
    }
    if (currentPenalties < bestPenalties)
        return -1;
    if (bestPenalties < currentPenalties)
        return 1;
    // 2. best priority & alternativity including free time requests
    if (ft) {
        for (int idx = 0; idx < current.length; idx++) {
            if (best[idx] != null && best[idx].getAssignments() != null) {
                if (current[idx] == null || current[idx].getSections() == null)
                    // higher priority request assigned
                    return 1;
                if (best[idx].getTruePriority() < current[idx].getTruePriority())
                    // less alternative request assigned
                    return 1;
                if (best[idx].getTruePriority() > current[idx].getTruePriority())
                    // less alternative request assigned
                    return -1;
            } else {
                if (current[idx] != null && current[idx].getAssignments() != null)
                    // higher priority request assigned
                    return -1;
            }
        }
    }
    // 3. maximize selection
    int bestSelected = 0, currentSelected = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
            Set<Section> preferred = getPreferredSections(best[idx].getRequest());
            if (preferred != null && !preferred.isEmpty()) {
                for (Section section : best[idx].getSections()) if (preferred.contains(section))
                    bestSelected++;
                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;
    // 3.9 maximize selection with penalization for not followed reservations
    if (res) {
        for (int idx = 0; idx < current.length; idx++) {
            if (best[idx] != null && best[idx].getAssignments() != null) {
                if (current[idx] == null || current[idx].getSections() == null)
                    // higher priority request assigned
                    return 1;
                if (best[idx].getAdjustedPriority() < current[idx].getAdjustedPriority())
                    // less alternative request assigned
                    return 1;
                if (best[idx].getAdjustedPriority() > current[idx].getAdjustedPriority())
                    // less alternative request assigned
                    return -1;
            } else {
                if (current[idx] != null && current[idx].getAssignments() != null)
                    // higher priority request assigned
                    return -1;
            }
        }
    }
    // 3.95 avoid past sections
    int bestPast = 0, currentPast = 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.isPast())
                    bestPast++;
            }
        }
        if (current[idx] != null && current[idx].getAssignments() != null) {
            for (Section section : current[idx].getSections()) {
                if (section.isPast())
                    currentPast++;
            }
        }
    }
    if (currentPast < bestPast)
        return -1;
    if (bestPast < currentPast)
        return 1;
    // 4-5. student quality
    if (getModel().getStudentQuality() != null) {
        double bestQuality = 0, currentQuality = 0;
        for (StudentQuality.Type type : StudentQuality.Type.values()) {
            for (int idx = 0; idx < current.length; idx++) {
                if (best[idx] != null && best[idx].getAssignments() != null) {
                    bestQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, best[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (best[x] != null && best[x].getAssignments() != null)
                            bestQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, best[x], best[idx]);
                    }
                }
                if (current[idx] != null && current[idx].getAssignments() != null) {
                    currentQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, current[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (current[x] != null && current[x].getAssignments() != null)
                            currentQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, current[x], current[idx]);
                    }
                }
            }
        }
        if (currentQuality < bestQuality)
            return -1;
        if (bestQuality < currentQuality)
            return 1;
    } else {
        // 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]);
                    }
                    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) {
                    bestDistanceConf += getModel().getDistanceConflict().nrConflicts(best[idx]);
                    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) {
                    currentDistanceConf += getModel().getDistanceConflict().nrConflicts(current[idx]);
                    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 and online sections (no-time first, online second)
    int bestNoTime = 0, currentNoTime = 0;
    int bestOnline = 0, currentOnline = 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.hasTime())
                    bestNoTime++;
                if (section.isOnline())
                    bestOnline++;
            }
            for (Section section : current[idx].getSections()) {
                if (!section.hasTime())
                    currentNoTime++;
                if (section.isOnline())
                    currentOnline++;
            }
        }
    }
    if (currentNoTime < bestNoTime)
        return -1;
    if (bestNoTime < currentNoTime)
        return 1;
    if (currentOnline < bestOnline)
        return -1;
    if (bestOnline < currentOnline)
        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++;
            }
            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() / best[idx].getSections().size();
            for (Section section : current[idx].getSections()) currentPenalty += section.getPenalty() / current[idx].getSections().size();
        }
    }
    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) StudentQuality(org.cpsolver.studentsct.extension.StudentQuality) Subpart(org.cpsolver.studentsct.model.Subpart) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Section(org.cpsolver.studentsct.model.Section)

Example 30 with CourseRequest

use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.

the class OnlineSectioningCriterion 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;
    boolean ft = false;
    boolean res = false;
    for (int idx = 0; idx < current.length; idx++) {
        if (isFreeTime(idx)) {
            ft = true;
            continue;
        }
        Request request = getRequest(idx);
        if (request instanceof CourseRequest && ((CourseRequest) request).hasReservations())
            res = true;
        if (idx < maxIdx) {
            if (best[idx] != null) {
                if (current[idx] == null)
                    // higher priority request assigned
                    return false;
                if (best[idx].getTruePriority() < current[idx].getTruePriority())
                    // less alternative request assigned
                    return false;
                if (best[idx].getTruePriority() > current[idx].getTruePriority())
                    // less alternative request assigned
                    return true;
                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].getTruePriority() > 0)
                    // alternativity can be improved
                    return true;
            } else {
                if (!request.isAlternative() || alt > 0)
                    // priority can be improved
                    return true;
            }
        }
    }
    // 0.1. allowed, but not available sections
    int notAvailable = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null && best[idx].getAssignments() != null && best[idx].getRequest() instanceof CourseRequest && best[idx].getReservation() != null && best[idx].getReservation().canAssignOverLimit()) {
            for (Section section : best[idx].getSections()) {
                if (section.getLimit() == 0)
                    notAvailable++;
            }
        }
        if (idx < maxIdx && current[idx] != null && current[idx].getAssignments() != null && current[idx].getRequest() instanceof CourseRequest && current[idx].getReservation() != null && current[idx].getReservation().canAssignOverLimit()) {
            for (Section section : current[idx].getSections()) {
                if (section.getLimit() == 0)
                    notAvailable--;
            }
        }
    }
    if (notAvailable > 0) {
        return true;
    }
    // 0.5. avoid course time overlaps & unavailability overlaps
    if (getModel().getStudentQuality() != null) {
        int bestTimeOverlaps = 0, currentTimeOverlaps = 0;
        for (int idx = 0; idx < current.length; idx++) {
            if (best[idx] != null && best[idx].getRequest() instanceof CourseRequest) {
                for (int x = 0; x < idx; x++) {
                    if (best[x] != null && best[x].getRequest() instanceof CourseRequest)
                        bestTimeOverlaps += getModel().getStudentQuality().penalty(StudentQuality.Type.CourseTimeOverlap, best[x], best[idx]);
                }
            }
            if (current[idx] != null && idx < maxIdx && current[idx].getRequest() instanceof CourseRequest) {
                for (int x = 0; x < idx; x++) {
                    if (current[x] != null && current[x].getRequest() instanceof CourseRequest)
                        currentTimeOverlaps += getModel().getStudentQuality().penalty(StudentQuality.Type.CourseTimeOverlap, 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().getStudentQuality().penalty(StudentQuality.Type.Unavailability, best[idx]);
            }
            if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
                currentTimeOverlaps += getModel().getStudentQuality().penalty(StudentQuality.Type.Unavailability, current[idx]);
            }
        }
        if (currentTimeOverlaps < bestTimeOverlaps)
            return true;
        if (bestTimeOverlaps < currentTimeOverlaps)
            return false;
    } else if (getModel().getTimeOverlaps() != null) {
        int bestTimeOverlaps = 0, currentTimeOverlaps = 0;
        for (int idx = 0; idx < current.length; idx++) {
            if (best[idx] != null && best[idx].getRequest() instanceof CourseRequest) {
                for (int x = 0; x < idx; x++) {
                    if (best[x] != null && best[x].getRequest() instanceof CourseRequest)
                        bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(best[x], best[idx]);
                }
            }
            if (current[idx] != null && idx < maxIdx && current[idx].getRequest() instanceof CourseRequest) {
                for (int x = 0; x < idx; x++) {
                    if (current[x] != null && current[x].getRequest() instanceof CourseRequest)
                        currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(current[x], current[idx]);
                }
            }
        }
        for (int idx = 0; idx < current.length; idx++) {
            if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
                bestTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(best[idx]);
            }
            if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
                currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
            }
        }
        if (currentTimeOverlaps < bestTimeOverlaps)
            return true;
        if (bestTimeOverlaps < currentTimeOverlaps)
            return false;
    }
    // 1. maximize number of penalties
    double bestPenalties = 0, currentPenalties = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null) {
            for (Section section : best[idx].getSections()) bestPenalties += getModel().getOverExpected(assignment, best, idx, section, best[idx].getRequest());
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) currentPenalties += getModel().getOverExpected(assignment, current, idx, section, current[idx].getRequest());
        }
    }
    if (currentPenalties < bestPenalties)
        return true;
    if (bestPenalties < currentPenalties)
        return false;
    // 2. best priority & alternativity including free times
    if (ft) {
        alt = 0;
        for (int idx = 0; idx < current.length; idx++) {
            Request request = getStudent().getRequests().get(idx);
            if (idx < maxIdx) {
                if (best[idx] != null) {
                    if (current[idx] == null)
                        // higher priority request assigned
                        return false;
                    if (best[idx].getTruePriority() < current[idx].getTruePriority())
                        // less alternative request assigned
                        return false;
                    if (best[idx].getTruePriority() > current[idx].getTruePriority())
                        // less alternative request assigned
                        return true;
                    if (request.isAlternative())
                        alt--;
                } else {
                    if (current[idx] != null)
                        // higher priority request assigned
                        return true;
                    if (request instanceof CourseRequest && !request.isAlternative())
                        alt++;
                }
            } else {
                if (best[idx] != null) {
                    if (best[idx].getTruePriority() > 0)
                        // alternativity can be improved
                        return true;
                } else {
                    if (!request.isAlternative() || alt > 0)
                        // priority can be improved
                        return true;
                }
            }
        }
    }
    // 3. maximize selection
    int bestSelected = 0, currentSelected = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null && best[idx].isCourseRequest()) {
            Set<Section> preferred = getPreferredSections(best[idx].getRequest());
            if (preferred != null && !preferred.isEmpty()) {
                for (Section section : best[idx].getSections()) if (preferred.contains(section)) {
                    if (idx < maxIdx)
                        bestSelected++;
                } else if (idx >= maxIdx)
                    bestSelected--;
            }
        }
        if (current[idx] != null && idx < maxIdx && current[idx].isCourseRequest()) {
            Set<Section> preferred = getPreferredSections(current[idx].getRequest());
            if (preferred != null && !preferred.isEmpty()) {
                for (Section section : current[idx].getSections()) if (preferred.contains(section))
                    currentSelected++;
            }
        }
    }
    if (currentSelected > bestSelected)
        return true;
    if (bestSelected > currentSelected)
        return false;
    // 3.5 maximize preferences
    double bestSelectedConfigs = 0, currentSelectedConfigs = 0;
    double bestSelectedSections = 0, currentSelectedSections = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
            bestSelectedSections += best[idx].percentSelectedSameSection();
            bestSelectedConfigs += best[idx].percentSelectedSameConfig();
            if (idx >= maxIdx) {
                bestSelectedSections -= 1.0;
                bestSelectedConfigs -= 1.0;
            }
        }
        if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
            currentSelectedSections += current[idx].percentSelectedSameSection();
            currentSelectedConfigs += current[idx].percentSelectedSameConfig();
        }
    }
    if (0.3 * currentSelectedConfigs + 0.7 * currentSelectedSections > 0.3 * bestSelectedConfigs + 0.7 * bestSelectedSections)
        return true;
    if (0.3 * bestSelectedConfigs + 0.7 * bestSelectedSections > 0.3 * currentSelectedConfigs + 0.7 * currentSelectedSections)
        return false;
    // 3.9 maximize selection with penalization for not followed reservations
    if (res) {
        alt = 0;
        for (int idx = 0; idx < current.length; idx++) {
            Request request = getStudent().getRequests().get(idx);
            if (idx < maxIdx) {
                if (best[idx] != null) {
                    if (current[idx] == null)
                        // higher priority request assigned
                        return false;
                    if (best[idx].getAdjustedPriority() < current[idx].getAdjustedPriority())
                        // less alternative request assigned
                        return false;
                    if (best[idx].getAdjustedPriority() > current[idx].getAdjustedPriority())
                        // less alternative request assigned
                        return true;
                    if (request.isAlternative())
                        alt--;
                } else {
                    if (current[idx] != null)
                        // higher priority request assigned
                        return true;
                    if (request instanceof CourseRequest && !request.isAlternative())
                        alt++;
                }
            } else {
                if (best[idx] != null) {
                    if (best[idx].getTruePriority() > 0)
                        // alternativity can be improved
                        return true;
                } else {
                    if (!request.isAlternative() || alt > 0)
                        // priority can be improved
                        return true;
                }
            }
        }
    }
    // 3.95 avoid past sections
    int bestPast = 0, currentPast = 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.isPast())
                    bestPast++;
            }
        }
        if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null) {
            for (Section section : current[idx].getSections()) {
                if (section.isPast())
                    currentPast++;
            }
        }
    }
    if (currentPast < bestPast)
        return true;
    if (bestPast < currentPast)
        return false;
    // 4-5. student quality
    if (getModel().getStudentQuality() != null) {
        double bestQuality = 0, currentQuality = 0;
        for (StudentQuality.Type type : StudentQuality.Type.values()) {
            for (int idx = 0; idx < current.length; idx++) {
                if (best[idx] != null) {
                    bestQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, best[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (best[x] != null)
                            bestQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, best[x], best[idx]);
                    }
                }
                if (current[idx] != null && idx < maxIdx) {
                    currentQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, current[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (current[x] != null)
                            currentQuality += iQalityWeights[type.ordinal()] * getModel().getStudentQuality().penalty(type, current[x], current[idx]);
                    }
                }
            }
        }
        if (currentQuality < bestQuality)
            return true;
        if (bestQuality < currentQuality)
            return false;
    } else {
        // 4. avoid time overlaps
        if (getModel().getTimeOverlaps() != null) {
            int bestTimeOverlaps = 0, currentTimeOverlaps = 0;
            for (int idx = 0; idx < current.length; idx++) {
                if (best[idx] != null) {
                    for (int x = 0; x < idx; x++) {
                        if (best[x] != null)
                            bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(best[x], best[idx]);
                        else if (getStudent().getRequests().get(x) instanceof FreeTimeRequest)
                            bestTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(((FreeTimeRequest) getStudent().getRequests().get(x)).createEnrollment(), best[idx]);
                    }
                }
                if (current[idx] != null && idx < maxIdx) {
                    for (int x = 0; x < idx; x++) {
                        if (current[x] != null)
                            currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(current[x], current[idx]);
                        else if (getStudent().getRequests().get(x) instanceof FreeTimeRequest)
                            currentTimeOverlaps += getModel().getTimeOverlaps().nrConflicts(((FreeTimeRequest) getStudent().getRequests().get(x)).createEnrollment(), current[idx]);
                    }
                }
            }
            for (int idx = 0; idx < current.length; idx++) {
                if (best[idx] != null && best[idx].getAssignments() != null && best[idx].isCourseRequest()) {
                    bestTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(best[idx]);
                }
                if (current[idx] != null && idx < maxIdx && current[idx].getAssignments() != null && current[idx].isCourseRequest()) {
                    currentTimeOverlaps += getModel().getTimeOverlaps().nrNotAvailableTimeConflicts(current[idx]);
                }
            }
            if (currentTimeOverlaps < bestTimeOverlaps)
                return true;
            if (bestTimeOverlaps < currentTimeOverlaps)
                return false;
        }
        // 5. avoid distance conflicts
        if (getModel().getDistanceConflict() != null) {
            int bestDistanceConf = 0, currentDistanceConf = 0;
            for (int idx = 0; idx < current.length; idx++) {
                if (best[idx] != null) {
                    bestDistanceConf += getModel().getDistanceConflict().nrConflicts(best[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (best[x] != null)
                            bestDistanceConf += getModel().getDistanceConflict().nrConflicts(best[x], best[idx]);
                    }
                }
                if (current[idx] != null && idx < maxIdx) {
                    currentDistanceConf += getModel().getDistanceConflict().nrConflicts(current[idx]);
                    for (int x = 0; x < idx; x++) {
                        if (current[x] != null)
                            currentDistanceConf += getModel().getDistanceConflict().nrConflicts(current[x], current[idx]);
                    }
                }
            }
            if (currentDistanceConf < bestDistanceConf)
                return true;
            if (bestDistanceConf < currentDistanceConf)
                return false;
        }
    }
    // 6. avoid no-time and online sections (no-time first, online second)
    int bestNoTime = 0, currentNoTime = 0;
    int bestOnline = 0, currentOnline = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null) {
            for (Section section : best[idx].getSections()) {
                if (!section.hasTime())
                    bestNoTime++;
                if (section.isOnline())
                    bestOnline++;
            }
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) {
                if (!section.hasTime())
                    currentNoTime++;
                if (section.isOnline())
                    currentOnline++;
            }
        }
    }
    if (currentNoTime < bestNoTime)
        return true;
    if (bestNoTime < currentNoTime)
        return false;
    if (currentOnline < bestOnline)
        return true;
    if (bestOnline < currentOnline)
        return false;
    // 7. balance sections
    double bestUnavailableSize = 0.0, currentUnavailableSize = 0.0;
    int bestAltSectionsWithLimit = 0, currentAltSectionsWithLimit = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null) {
            for (Section section : best[idx].getSections()) {
                Subpart subpart = section.getSubpart();
                // skip unlimited and single section subparts
                if (subpart.getSections().size() <= 1 || subpart.getLimit() <= 0)
                    continue;
                // average size
                double averageSize = ((double) subpart.getLimit()) / subpart.getSections().size();
                // section is below average
                if (section.getLimit() < averageSize)
                    bestUnavailableSize += (averageSize - section.getLimit()) / averageSize;
                bestAltSectionsWithLimit++;
            }
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) {
                Subpart subpart = section.getSubpart();
                // skip unlimited and single section subparts
                if (subpart.getSections().size() <= 1 || subpart.getLimit() <= 0)
                    continue;
                // average size
                double averageSize = ((double) subpart.getLimit()) / subpart.getSections().size();
                // section is below average
                if (section.getLimit() < averageSize)
                    currentUnavailableSize += (averageSize - section.getLimit()) / averageSize;
                currentAltSectionsWithLimit++;
            }
        }
    }
    double bestUnavailableSizeFraction = (bestUnavailableSize > 0 ? bestUnavailableSize / bestAltSectionsWithLimit : 0.0);
    double currentUnavailableSizeFraction = (currentUnavailableSize > 0 ? currentUnavailableSize / currentAltSectionsWithLimit : 0.0);
    if (currentUnavailableSizeFraction < bestUnavailableSizeFraction)
        return true;
    if (bestUnavailableSizeFraction < currentUnavailableSizeFraction)
        return false;
    // 8. average penalty sections
    double bestPenalty = 0.0, currentPenalty = 0.0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null) {
            for (Section section : best[idx].getSections()) bestPenalty += section.getPenalty() / best[idx].getSections().size();
            if (idx >= maxIdx && best[idx].isCourseRequest())
                bestPenalty -= ((CourseRequest) best[idx].getRequest()).getMinPenalty();
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) currentPenalty += section.getPenalty() / current[idx].getSections().size();
        }
    }
    if (currentPenalty < bestPenalty)
        return true;
    if (bestPenalty < currentPenalty)
        return false;
    return true;
}
Also used : FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) StudentQuality(org.cpsolver.studentsct.extension.StudentQuality) Subpart(org.cpsolver.studentsct.model.Subpart) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Section(org.cpsolver.studentsct.model.Section)

Aggregations

CourseRequest (org.cpsolver.studentsct.model.CourseRequest)67 Request (org.cpsolver.studentsct.model.Request)51 Enrollment (org.cpsolver.studentsct.model.Enrollment)37 Section (org.cpsolver.studentsct.model.Section)36 Course (org.cpsolver.studentsct.model.Course)26 FreeTimeRequest (org.cpsolver.studentsct.model.FreeTimeRequest)21 Subpart (org.cpsolver.studentsct.model.Subpart)21 ArrayList (java.util.ArrayList)20 HashSet (java.util.HashSet)18 Student (org.cpsolver.studentsct.model.Student)17 HashMap (java.util.HashMap)15 Config (org.cpsolver.studentsct.model.Config)13 Map (java.util.Map)11 Offering (org.cpsolver.studentsct.model.Offering)10 CSVFile (org.cpsolver.ifs.util.CSVFile)9 Set (java.util.Set)8 DistanceConflict (org.cpsolver.studentsct.extension.DistanceConflict)7 TreeSet (java.util.TreeSet)6 Constraint (org.cpsolver.ifs.model.Constraint)6 StudentQuality (org.cpsolver.studentsct.extension.StudentQuality)6