Search in sources :

Example 41 with CourseRequest

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

the class MaxOverExpectedConstraint method computeConflicts.

@Override
public void computeConflicts(Assignment<Request, Enrollment> assignment, Enrollment value, Set<Enrollment> conflicts) {
    if (!value.isCourseRequest())
        return;
    CourseRequest cr = (CourseRequest) value.variable();
    OnlineSectioningModel model = (OnlineSectioningModel) getModel();
    double basePenalty = model.getOverExpected(assignment, value, value, conflicts);
    if (basePenalty > iMaxOverExpected) {
        conflicts.add(value);
        return;
    }
    RouletteWheelSelection<Enrollment> selection = new RouletteWheelSelection<Enrollment>();
    for (Request r : cr.getStudent().getRequests()) {
        Enrollment e = assignment.getValue(r);
        if (e != null && !r.equals(value.variable()) && !conflicts.contains(e) && e.isCourseRequest()) {
            double penalty = model.getOverExpected(assignment, e, value, conflicts);
            if (penalty > 0.0)
                selection.add(e, penalty);
        }
    }
    while (selection.getRemainingPoints() + basePenalty > iMaxOverExpected && selection.hasMoreElements()) {
        conflicts.add(selection.nextElement());
    }
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) RouletteWheelSelection(org.cpsolver.ifs.heuristics.RouletteWheelSelection) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Request(org.cpsolver.studentsct.model.Request) Enrollment(org.cpsolver.studentsct.model.Enrollment)

Example 42 with CourseRequest

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

the class PriorityStudentWeights method getWeight.

@Override
public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment) {
    double weight = getCachedWeight(enrollment.getRequest());
    switch(enrollment.getPriority()) {
        case 1:
            weight *= iFirstAlternativeFactor;
            break;
        case 2:
            weight *= iSecondAlternativeFactor;
            break;
    }
    if (enrollment.isCourseRequest() && iBalancingFactor != 0.0) {
        double configUsed = enrollment.getConfig().getEnrollmentTotalWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight();
        double disbalanced = 0;
        double total = 0;
        for (Section section : enrollment.getSections()) {
            Subpart subpart = section.getSubpart();
            if (subpart.getSections().size() <= 1)
                continue;
            double used = section.getEnrollmentTotalWeight(assignment, enrollment.getRequest()) + enrollment.getRequest().getWeight();
            // sections have limits -> desired size is section limit x (total enrollment / total limit)
            // unlimited sections -> desired size is total enrollment / number of sections
            double desired = (subpart.getLimit() > 0 ? section.getLimit() * (configUsed / subpart.getLimit()) : configUsed / subpart.getSections().size());
            if (used > desired)
                disbalanced += Math.min(enrollment.getRequest().getWeight(), used - desired) / enrollment.getRequest().getWeight();
            else
                disbalanced -= Math.min(enrollment.getRequest().getWeight(), desired - used) / enrollment.getRequest().getWeight();
            total++;
        }
        if (disbalanced > 0)
            weight *= (1.0 - disbalanced / total * iBalancingFactor);
    }
    if (iMPP) {
        double difference = getDifference(enrollment);
        if (difference > 0.0)
            weight *= (1.0 - difference * iPerturbationFactor);
    }
    if (iSelectionFactor != 0.0) {
        double selection = getSelection(enrollment);
        if (selection > 0.0)
            weight *= (1.0 - selection * iSelectionFactor);
    }
    if (enrollment.isCourseRequest() && iGroupFactor != 0.0) {
        double sameGroup = 0.0;
        int groupCount = 0;
        for (RequestGroup g : ((CourseRequest) enrollment.getRequest()).getRequestGroups()) {
            if (g.getCourse().equals(enrollment.getCourse())) {
                sameGroup += g.getEnrollmentSpread(assignment, enrollment, iGroupBestRatio, iGroupFillRatio);
                groupCount++;
            }
        }
        if (groupCount > 0) {
            double difference = 1.0 - sameGroup / groupCount;
            weight *= (1.0 - difference * iGroupFactor);
        }
    }
    return round(weight);
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Subpart(org.cpsolver.studentsct.model.Subpart) RequestGroup(org.cpsolver.studentsct.model.RequestGroup) Section(org.cpsolver.studentsct.model.Section)

Example 43 with CourseRequest

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

the class StudentSectioningXMLLoader method loadCourseRequest.

/**
 * Load course request
 * @param requestEl request element
 * @param student parent student
 * @param offeringTable offering table
 * @param courseTable course table
 * @return loaded course request
 */
public CourseRequest loadCourseRequest(Element requestEl, Student student, Map<Long, Offering> offeringTable, Map<Long, Course> courseTable) {
    List<Course> courses = new ArrayList<Course>();
    courses.add(courseTable.get(Long.valueOf(requestEl.attributeValue("course"))));
    for (Iterator<?> k = requestEl.elementIterator("alternative"); k.hasNext(); ) courses.add(courseTable.get(Long.valueOf(((Element) k.next()).attributeValue("course"))));
    Long timeStamp = null;
    if (requestEl.attributeValue("timeStamp") != null)
        timeStamp = Long.valueOf(requestEl.attributeValue("timeStamp"));
    CourseRequest courseRequest = new CourseRequest(Long.parseLong(requestEl.attributeValue("id")), Integer.parseInt(requestEl.attributeValue("priority")), "true".equals(requestEl.attributeValue("alternative")), student, courses, "true".equals(requestEl.attributeValue("waitlist", "false")), RequestPriority.valueOf(requestEl.attributeValue("importance", "true".equals(requestEl.attributeValue("critical", "false")) ? RequestPriority.Critical.name() : RequestPriority.Normal.name())), timeStamp);
    if (iWaitlistCritical && RequestPriority.Critical.isCritical(courseRequest) && !courseRequest.isAlternative())
        courseRequest.setWaitlist(true);
    if (requestEl.attributeValue("weight") != null)
        courseRequest.setWeight(Double.parseDouble(requestEl.attributeValue("weight")));
    for (Iterator<?> k = requestEl.elementIterator("waitlisted"); k.hasNext(); ) {
        Element choiceEl = (Element) k.next();
        courseRequest.getWaitlistedChoices().add(new Choice(offeringTable.get(Long.valueOf(choiceEl.attributeValue("offering"))), choiceEl.getText()));
    }
    for (Iterator<?> k = requestEl.elementIterator("selected"); k.hasNext(); ) {
        Element choiceEl = (Element) k.next();
        courseRequest.getSelectedChoices().add(new Choice(offeringTable.get(Long.valueOf(choiceEl.attributeValue("offering"))), choiceEl.getText()));
    }
    for (Iterator<?> k = requestEl.elementIterator("required"); k.hasNext(); ) {
        Element choiceEl = (Element) k.next();
        courseRequest.getRequiredChoices().add(new Choice(offeringTable.get(Long.valueOf(choiceEl.attributeValue("offering"))), choiceEl.getText()));
    }
    groups: for (Iterator<?> k = requestEl.elementIterator("group"); k.hasNext(); ) {
        Element groupEl = (Element) k.next();
        long gid = Long.parseLong(groupEl.attributeValue("id"));
        String gname = groupEl.attributeValue("name", "g" + gid);
        Course course = courseTable.get(Long.valueOf(groupEl.attributeValue("course")));
        for (RequestGroup g : course.getRequestGroups()) {
            if (g.getId() == gid) {
                courseRequest.addRequestGroup(g);
                continue groups;
            }
        }
        courseRequest.addRequestGroup(new RequestGroup(gid, gname, course));
    }
    return courseRequest;
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Choice(org.cpsolver.studentsct.model.Choice) RequestGroup(org.cpsolver.studentsct.model.RequestGroup) Element(org.dom4j.Element) ArrayList(java.util.ArrayList) Iterator(java.util.Iterator) Course(org.cpsolver.studentsct.model.Course)

Example 44 with CourseRequest

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

the class Test method fixWeights.

private static void fixWeights(StudentSectioningModel model) {
    HashMap<Course, Integer> lastLike = new HashMap<Course, Integer>();
    HashMap<Course, Integer> real = new HashMap<Course, Integer>();
    HashSet<Long> lastLikeIds = new HashSet<Long>();
    HashSet<Long> realIds = new HashSet<Long>();
    for (Student student : model.getStudents()) {
        if (student.isDummy()) {
            if (!lastLikeIds.add(Long.valueOf(student.getId()))) {
                sLog.error("Two last-like student with id " + student.getId());
            }
        } else {
            if (!realIds.add(Long.valueOf(student.getId()))) {
                sLog.error("Two real student with id " + student.getId());
            }
        }
        for (Request request : student.getRequests()) {
            if (request instanceof CourseRequest) {
                CourseRequest courseRequest = (CourseRequest) request;
                Course course = courseRequest.getCourses().get(0);
                Integer cnt = (student.isDummy() ? lastLike : real).get(course);
                (student.isDummy() ? lastLike : real).put(course, Integer.valueOf((cnt == null ? 0 : cnt.intValue()) + 1));
            }
        }
    }
    for (Student student : new ArrayList<Student>(model.getStudents())) {
        if (student.isDummy() && realIds.contains(Long.valueOf(student.getId()))) {
            sLog.warn("There is both last-like and real student with id " + student.getId());
            long newId = -1;
            while (true) {
                newId = 1 + (long) (999999999L * Math.random());
                if (!realIds.contains(Long.valueOf(newId)) && !lastLikeIds.contains(Long.valueOf(newId)))
                    break;
            }
            lastLikeIds.remove(Long.valueOf(student.getId()));
            lastLikeIds.add(Long.valueOf(newId));
            student.setId(newId);
            sLog.warn("  -- last-like student id changed to " + student.getId());
        }
        for (Request request : new ArrayList<Request>(student.getRequests())) {
            if (!student.isDummy()) {
                request.setWeight(1.0);
                continue;
            }
            if (request instanceof CourseRequest) {
                CourseRequest courseRequest = (CourseRequest) request;
                Course course = courseRequest.getCourses().get(0);
                Integer lastLikeCnt = lastLike.get(course);
                Integer realCnt = real.get(course);
                courseRequest.setWeight(getLastLikeStudentWeight(course, realCnt == null ? 0 : realCnt.intValue(), lastLikeCnt == null ? 0 : lastLikeCnt.intValue()));
            } else
                request.setWeight(1.0);
            if (request.getWeight() <= 0.0) {
                model.removeVariable(request);
                student.getRequests().remove(request);
            }
        }
        if (student.getRequests().isEmpty()) {
            model.getStudents().remove(student);
        }
    }
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) HashMap(java.util.HashMap) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) ArrayList(java.util.ArrayList) Course(org.cpsolver.studentsct.model.Course) Student(org.cpsolver.studentsct.model.Student) HashSet(java.util.HashSet)

Example 45 with CourseRequest

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

the class Test method onlineSectioning.

/**
 * Online sectioning test
 * @param cfg solver configuration
 * @return resultant solution
 * @throws Exception thrown when the sectioning fails
 */
public static Solution<Request, Enrollment> onlineSectioning(DataProperties cfg) throws Exception {
    Solution<Request, Enrollment> solution = load(cfg);
    if (solution == null)
        return null;
    StudentSectioningModel model = (StudentSectioningModel) solution.getModel();
    Assignment<Request, Enrollment> assignment = solution.getAssignment();
    solution.addSolutionListener(new TestSolutionListener());
    double startTime = JProf.currentTimeSec();
    Solver<Request, Enrollment> solver = new Solver<Request, Enrollment>(cfg);
    solver.setInitalSolution(solution);
    solver.initSolver();
    OnlineSelection onlineSelection = new OnlineSelection(cfg);
    onlineSelection.init(solver);
    double totalPenalty = 0, minPenalty = 0, maxPenalty = 0;
    double minAvEnrlPenalty = 0, maxAvEnrlPenalty = 0;
    double totalPrefPenalty = 0, minPrefPenalty = 0, maxPrefPenalty = 0;
    double minAvEnrlPrefPenalty = 0, maxAvEnrlPrefPenalty = 0;
    int nrChoices = 0, nrEnrollments = 0, nrCourseRequests = 0;
    int chChoices = 0, chCourseRequests = 0, chStudents = 0;
    int choiceLimit = model.getProperties().getPropertyInt("Test.ChoicesLimit", -1);
    File outDir = new File(model.getProperties().getProperty("General.Output", "."));
    outDir.mkdirs();
    PrintWriter pw = new PrintWriter(new FileWriter(new File(outDir, "choices.csv")));
    List<Student> students = model.getStudents();
    try {
        @SuppressWarnings("rawtypes") Class studentOrdClass = Class.forName(model.getProperties().getProperty("Test.StudentOrder", StudentRandomOrder.class.getName()));
        @SuppressWarnings("unchecked") StudentOrder studentOrd = (StudentOrder) studentOrdClass.getConstructor(new Class[] { DataProperties.class }).newInstance(new Object[] { model.getProperties() });
        students = studentOrd.order(model.getStudents());
    } catch (Exception e) {
        sLog.error("Unable to reorder students, reason: " + e.getMessage(), e);
    }
    ShutdownHook hook = new ShutdownHook(solver);
    Runtime.getRuntime().addShutdownHook(hook);
    for (Student student : students) {
        if (student.nrAssignedRequests(assignment) > 0)
            // skip students with assigned courses (i.e., students
            continue;
        // already assigned by a batch sectioning process)
        sLog.info("Sectioning student: " + student);
        BranchBoundSelection.Selection selection = onlineSelection.getSelection(assignment, student);
        BranchBoundNeighbour neighbour = selection.select();
        if (neighbour != null) {
            StudentPreferencePenalties penalties = null;
            if (selection instanceof OnlineSelection.EpsilonSelection) {
                OnlineSelection.EpsilonSelection epsSelection = (OnlineSelection.EpsilonSelection) selection;
                penalties = epsSelection.getPenalties();
                for (int i = 0; i < neighbour.getAssignment().length; i++) {
                    Request r = student.getRequests().get(i);
                    if (r instanceof CourseRequest) {
                        nrCourseRequests++;
                        chCourseRequests++;
                        int chChoicesThisRq = 0;
                        CourseRequest request = (CourseRequest) r;
                        for (Enrollment x : request.getAvaiableEnrollments(assignment)) {
                            nrEnrollments++;
                            if (epsSelection.isAllowed(i, x)) {
                                nrChoices++;
                                if (choiceLimit <= 0 || chChoicesThisRq < choiceLimit) {
                                    chChoices++;
                                    chChoicesThisRq++;
                                }
                            }
                        }
                    }
                }
                chStudents++;
                if (chStudents == 100) {
                    pw.println(sDF.format(((double) chChoices) / chCourseRequests));
                    pw.flush();
                    chStudents = 0;
                    chChoices = 0;
                    chCourseRequests = 0;
                }
            }
            for (int i = 0; i < neighbour.getAssignment().length; i++) {
                if (neighbour.getAssignment()[i] == null)
                    continue;
                Enrollment enrollment = neighbour.getAssignment()[i];
                if (enrollment.getRequest() instanceof CourseRequest) {
                    CourseRequest request = (CourseRequest) enrollment.getRequest();
                    double[] avEnrlMinMax = getMinMaxAvailableEnrollmentPenalty(assignment, request);
                    minAvEnrlPenalty += avEnrlMinMax[0];
                    maxAvEnrlPenalty += avEnrlMinMax[1];
                    totalPenalty += enrollment.getPenalty();
                    minPenalty += request.getMinPenalty();
                    maxPenalty += request.getMaxPenalty();
                    if (penalties != null) {
                        double[] avEnrlPrefMinMax = penalties.getMinMaxAvailableEnrollmentPenalty(assignment, enrollment.getRequest());
                        minAvEnrlPrefPenalty += avEnrlPrefMinMax[0];
                        maxAvEnrlPrefPenalty += avEnrlPrefMinMax[1];
                        totalPrefPenalty += penalties.getPenalty(enrollment);
                        minPrefPenalty += penalties.getMinPenalty(enrollment.getRequest());
                        maxPrefPenalty += penalties.getMaxPenalty(enrollment.getRequest());
                    }
                }
            }
            neighbour.assign(assignment, solution.getIteration());
            sLog.info("Student " + student + " enrolls into " + neighbour);
            onlineSelection.updateSpace(assignment, student);
        } else {
            sLog.warn("No solution found.");
        }
        solution.update(JProf.currentTimeSec() - startTime);
        solution.saveBest();
    }
    if (chCourseRequests > 0)
        pw.println(sDF.format(((double) chChoices) / chCourseRequests));
    pw.flush();
    pw.close();
    HashMap<String, String> extra = new HashMap<String, String>();
    sLog.info("Overall penalty is " + getPerc(totalPenalty, minPenalty, maxPenalty) + "% (" + sDF.format(totalPenalty) + "/" + sDF.format(minPenalty) + ".." + sDF.format(maxPenalty) + ")");
    extra.put("Overall penalty", getPerc(totalPenalty, minPenalty, maxPenalty) + "% (" + sDF.format(totalPenalty) + "/" + sDF.format(minPenalty) + ".." + sDF.format(maxPenalty) + ")");
    extra.put("Overall available enrollment penalty", getPerc(totalPenalty, minAvEnrlPenalty, maxAvEnrlPenalty) + "% (" + sDF.format(totalPenalty) + "/" + sDF.format(minAvEnrlPenalty) + ".." + sDF.format(maxAvEnrlPenalty) + ")");
    if (onlineSelection.isUseStudentPrefPenalties()) {
        sLog.info("Overall preference penalty is " + getPerc(totalPrefPenalty, minPrefPenalty, maxPrefPenalty) + "% (" + sDF.format(totalPrefPenalty) + "/" + sDF.format(minPrefPenalty) + ".." + sDF.format(maxPrefPenalty) + ")");
        extra.put("Overall preference penalty", getPerc(totalPrefPenalty, minPrefPenalty, maxPrefPenalty) + "% (" + sDF.format(totalPrefPenalty) + "/" + sDF.format(minPrefPenalty) + ".." + sDF.format(maxPrefPenalty) + ")");
        extra.put("Overall preference available enrollment penalty", getPerc(totalPrefPenalty, minAvEnrlPrefPenalty, maxAvEnrlPrefPenalty) + "% (" + sDF.format(totalPrefPenalty) + "/" + sDF.format(minAvEnrlPrefPenalty) + ".." + sDF.format(maxAvEnrlPrefPenalty) + ")");
        extra.put("Average number of choices", sDF.format(((double) nrChoices) / nrCourseRequests) + " (" + nrChoices + "/" + nrCourseRequests + ")");
        extra.put("Average number of enrollments", sDF.format(((double) nrEnrollments) / nrCourseRequests) + " (" + nrEnrollments + "/" + nrCourseRequests + ")");
    }
    hook.setExtra(extra);
    return solution;
}
Also used : Solver(org.cpsolver.ifs.solver.Solver) ParallelSolver(org.cpsolver.ifs.solver.ParallelSolver) HashMap(java.util.HashMap) FileWriter(java.io.FileWriter) OnlineSelection(org.cpsolver.studentsct.heuristics.selection.OnlineSelection) Enrollment(org.cpsolver.studentsct.model.Enrollment) PrintWriter(java.io.PrintWriter) BranchBoundSelection(org.cpsolver.studentsct.heuristics.selection.BranchBoundSelection) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Student(org.cpsolver.studentsct.model.Student) IOException(java.io.IOException) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) BranchBoundNeighbour(org.cpsolver.studentsct.heuristics.selection.BranchBoundSelection.BranchBoundNeighbour) StudentOrder(org.cpsolver.studentsct.heuristics.studentord.StudentOrder) File(java.io.File)

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