Search in sources :

Example 1 with FreeTimeRequest

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

the class StudentRequestXml method exportModel.

public static Document exportModel(Assignment<Request, Enrollment> assignment, StudentSectioningModel model) {
    Document document = DocumentHelper.createDocument();
    Element requestElement = document.addElement("request");
    requestElement.addAttribute("campus", model.getProperties().getProperty("Data.Initiative"));
    requestElement.addAttribute("year", model.getProperties().getProperty("Data.Year"));
    requestElement.addAttribute("term", model.getProperties().getProperty("Data.Term"));
    for (Student student : model.getStudents()) {
        Element studentElement = requestElement.addElement("student");
        studentElement.addAttribute("key", String.valueOf(student.getId()));
        Element courseRequestsElement = studentElement.addElement("updateCourseRequests");
        courseRequestsElement.addAttribute("commit", "true");
        Collections.sort(student.getRequests(), new Comparator<Request>() {

            @Override
            public int compare(Request r1, Request r2) {
                if (r1.isAlternative() != r2.isAlternative()) {
                    return (r1.isAlternative() ? 1 : -1);
                }
                return Double.compare(r1.getPriority(), r2.getPriority());
            }
        });
        boolean hasSchedule = false;
        for (Request request : student.getRequests()) {
            if (assignment.getValue(request) != null)
                hasSchedule = true;
            if (request instanceof FreeTimeRequest) {
                FreeTimeRequest ftReq = (FreeTimeRequest) request;
                Element ftReqElement = courseRequestsElement.addElement("freeTime");
                requestElement.addAttribute("days", ftReq.getTime().getDayHeader());
                int startSlot = ftReq.getTime().getStartSlot();
                int startTime = startSlot * Constants.SLOT_LENGTH_MIN + Constants.FIRST_SLOT_TIME_MIN;
                ftReqElement.addAttribute("startTime", s2zDF.format(startTime / 60) + s2zDF.format(startTime % 60));
                int endTime = startTime + ftReq.getTime().getLength() * Constants.SLOT_LENGTH_MIN - ftReq.getTime().getBreakTime();
                ftReqElement.addAttribute("endTime", s2zDF.format(endTime / 60) + s2zDF.format(endTime % 60));
                ftReqElement.addAttribute("length", String.valueOf(ftReq.getTime().getLength() * Constants.SLOT_LENGTH_MIN));
            } else {
                CourseRequest crReq = (CourseRequest) request;
                Element crReqElement = courseRequestsElement.addElement("courseOffering");
                Course course = crReq.getCourses().get(0);
                crReqElement.addAttribute("subjectArea", course.getSubjectArea());
                crReqElement.addAttribute("courseNumber", course.getCourseNumber());
                crReqElement.addAttribute("waitlist", crReq.isWaitlist() ? "true" : "false");
                crReqElement.addAttribute("alternative", crReq.isAlternative() ? "true" : "false");
                for (int i = 1; i < crReq.getCourses().size(); i++) {
                    Course altCourse = crReq.getCourses().get(i);
                    Element altCourseElement = crReqElement.addElement("alternative");
                    altCourseElement.addAttribute("subjectArea", altCourse.getSubjectArea());
                    altCourseElement.addAttribute("courseNumber", altCourse.getCourseNumber());
                }
            }
        }
        if (hasSchedule) {
            Element requestScheduleElement = studentElement.addElement("requestSchedule");
            requestScheduleElement.addAttribute("type", "commit");
            for (Request request : student.getRequests()) {
                if (request instanceof CourseRequest) {
                    CourseRequest crReq = (CourseRequest) request;
                    Enrollment enrollment = assignment.getValue(crReq);
                    if (enrollment == null)
                        continue;
                    Element crReqElement = requestScheduleElement.addElement("courseOffering");
                    Course course = enrollment.getCourse();
                    crReqElement.addAttribute("subjectArea", course.getSubjectArea());
                    crReqElement.addAttribute("courseNumber", course.getCourseNumber());
                    for (Section section : enrollment.getSections()) {
                        Element classEl = crReqElement.addElement("class");
                        classEl.addAttribute("id", section.getSubpart().getInstructionalType());
                        classEl.addAttribute("assignmentId", String.valueOf(section.getId()));
                    }
                }
            }
        }
    }
    return document;
}
Also used : FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Element(org.dom4j.Element) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Document(org.dom4j.Document) Student(org.cpsolver.studentsct.model.Student) Section(org.cpsolver.studentsct.model.Section) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Enrollment(org.cpsolver.studentsct.model.Enrollment) Course(org.cpsolver.studentsct.model.Course)

Example 2 with FreeTimeRequest

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

the class InevitableStudentConflicts method check.

/** Check model for inevitable student conflicts 
     * @param assignment current assignment
     * @return true if there are no inevitable student conflicts
     **/
public boolean check(Assignment<Request, Enrollment> assignment) {
    sLog.info("Checking for inevitable student conflicts...");
    HashMap<TreeSet<Object>, Object[]> noGoods = new HashMap<TreeSet<Object>, Object[]>();
    long studentWithoutCompleteSchedule = 0;
    long inevitableRequests = 0;
    double inevitableRequestWeight = 0.0;
    long incompleteInevitableRequests = 0;
    double incompleteInevitableRequestWeight = 0.0;
    long total = 0;
    Comparator<Object> simpleCmp = new Comparator<Object>() {

        @Override
        public int compare(Object o1, Object o2) {
            return o1.toString().compareTo(o2.toString());
        }
    };
    HashSet<Request> requests2remove = new HashSet<Request>();
    for (Student student : getModel().getStudents()) {
        sLog.debug("  Checking " + (++total) + ". student " + student + "...");
        if (student.isComplete(assignment)) {
            for (Request request : student.getRequests()) {
                if (assignment.getValue(request) == null) {
                    inevitableRequests++;
                    inevitableRequestWeight += request.getWeight();
                }
            }
        } else {
            StudentCheck ch = new StudentCheck(student.getRequests());
            ch.check(assignment);
            if (!ch.isBestComplete()) {
                sLog.info("    Student " + student + " cannot have a complete schedule");
                studentWithoutCompleteSchedule++;
            }
            int idx = 0;
            for (Iterator<Request> f = student.getRequests().iterator(); f.hasNext(); idx++) {
                Request request = f.next();
                Enrollment enrollment = ch.getBestAssignment()[idx];
                if (enrollment == null) {
                    if (!ch.isBestComplete()) {
                        List<Request> noGood = noGood(assignment, student, ch, idx);
                        sLog.info("      Request " + request + " cannot be assigned");
                        for (Request r : noGood) {
                            sLog.debug("        " + r);
                            Collection<Enrollment> values = null;
                            if (r instanceof CourseRequest) {
                                values = ((CourseRequest) r).getEnrollmentsSkipSameTime(assignment);
                            } else {
                                values = request.computeEnrollments(assignment);
                            }
                            for (Enrollment en : values) {
                                sLog.debug("          " + enrollment2string(en));
                            }
                        }
                        if (iDeleteInevitable) {
                            // noGood.lastElement()
                            requests2remove.add(request);
                            sLog.info("        -- request " + request + " picked to be removed from the model");
                        }
                        TreeSet<Object> key = new TreeSet<Object>(simpleCmp);
                        for (Request r : noGood) {
                            if (r instanceof CourseRequest) {
                                key.add(((CourseRequest) r).getCourses().get(0));
                            } else {
                                key.add("Free " + ((FreeTimeRequest) r).getTime().getLongName(true));
                            }
                        }
                        Object[] counter = noGoods.get(key);
                        int ir = (counter == null ? 1 : ((Integer) counter[0]).intValue() + 1);
                        double irw = (counter == null ? 0.0 : ((Double) counter[1]).doubleValue()) + request.getWeight();
                        noGoods.put(key, new Object[] { new Integer(ir), new Double(irw) });
                        if (ch.canAssign(request, idx)) {
                            incompleteInevitableRequests++;
                            incompleteInevitableRequestWeight += request.getWeight();
                        }
                    }
                    inevitableRequests++;
                    inevitableRequestWeight += request.getWeight();
                }
            }
        }
    }
    for (Map.Entry<TreeSet<Object>, Object[]> entry : noGoods.entrySet()) {
        TreeSet<Object> noGood = entry.getKey();
        Object[] counter = entry.getValue();
        List<CSVFile.CSVField> fields = new ArrayList<CSVFile.CSVField>();
        String courseStr = "";
        for (Iterator<Object> j = noGood.iterator(); j.hasNext(); ) {
            Object x = j.next();
            if (x instanceof Course) {
                Course course = (Course) x;
                courseStr += course.getName();
            } else
                courseStr += x.toString();
            if (j.hasNext())
                courseStr += ", ";
        }
        fields.add(new CSVFile.CSVField(courseStr));
        fields.add(new CSVFile.CSVField(((Integer) counter[0]).intValue()));
        fields.add(new CSVFile.CSVField(((Double) counter[1]).doubleValue()));
        for (Iterator<Object> j = noGood.iterator(); j.hasNext(); ) {
            Object x = j.next();
            if (x instanceof Course) {
                Course course = (Course) x;
                List<Course> courses = new ArrayList<Course>(1);
                courses.add(course);
                CourseRequest cr = new CourseRequest(-1, 0, false, new Student(-1), courses, false, null);
                String field = course.getName();
                int idx = 0;
                for (Iterator<Enrollment> k = cr.getEnrollmentsSkipSameTime(assignment).iterator(); k.hasNext(); ) {
                    if (idx++ > 20) {
                        field += "\n ...";
                        break;
                    } else {
                        field += "\n  " + enrollment2string(k.next());
                    }
                }
                fields.add(new CSVFile.CSVField(field));
            } else
                fields.add(new CSVFile.CSVField(x.toString()));
        }
        iCSVFile.addLine(fields);
    }
    if (!requests2remove.isEmpty()) {
        for (Request request : requests2remove) {
            removeRequest(request);
        }
    }
    sLog.info("Students that can never obtain a complete schedule: " + studentWithoutCompleteSchedule);
    sLog.info("Inevitable student requests: " + inevitableRequests);
    sLog.info("Inevitable student request weight: " + inevitableRequestWeight);
    sLog.info("Inevitable student requests of students without a complete schedule: " + incompleteInevitableRequests);
    sLog.info("Inevitable student request weight of students without a complete schedule: " + incompleteInevitableRequestWeight);
    if (iCSVFile.getLines() != null)
        Collections.sort(iCSVFile.getLines(), new Comparator<CSVFile.CSVLine>() {

            @Override
            public int compare(CSVFile.CSVLine l1, CSVFile.CSVLine l2) {
                int cmp = Double.compare(l2.getField(1).toDouble(), l1.getField(1).toDouble());
                if (cmp != 0)
                    return cmp;
                return l1.getField(0).toString().compareTo(l2.getField(0).toString());
            }
        });
    return (inevitableRequests == 0);
}
Also used : CSVFile(org.cpsolver.ifs.util.CSVFile) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Comparator(java.util.Comparator) TreeSet(java.util.TreeSet) Enrollment(org.cpsolver.studentsct.model.Enrollment) Course(org.cpsolver.studentsct.model.Course) HashSet(java.util.HashSet) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Student(org.cpsolver.studentsct.model.Student) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) HashMap(java.util.HashMap) Map(java.util.Map)

Example 3 with FreeTimeRequest

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

the class TimeOverlapsCounter method allConflicts.

/**
     * The set of all conflicts ({@link Conflict} objects) of the given
     * enrollment and other enrollments that are assigned to the same student.
     * @param assignment current assignment
     * @param enrollment given enrollment
     * @return all conflicts of the given enrollment
     */
public Set<Conflict> allConflicts(Assignment<Request, Enrollment> assignment, Enrollment enrollment) {
    Set<Conflict> ret = new HashSet<Conflict>();
    if (enrollment.getRequest() instanceof FreeTimeRequest)
        return ret;
    for (Request request : enrollment.getStudent().getRequests()) {
        if (request.equals(enrollment.getRequest()))
            continue;
        Enrollment other = assignment.getValue(request);
        if (request instanceof FreeTimeRequest) {
            FreeTimeRequest ft = (FreeTimeRequest) request;
            ret.addAll(conflicts(enrollment, ft.createEnrollment()));
            continue;
        } else if (other != null) {
            ret.addAll(conflicts(enrollment, other));
        }
    }
    for (Unavailability unavailability : enrollment.getStudent().getUnavailabilities()) for (SctAssignment section : enrollment.getAssignments()) if (inConflict(section, unavailability))
        ret.add(new Conflict(enrollment.getStudent(), share(section, unavailability), enrollment, section, unavailability.createEnrollment(), unavailability));
    return ret;
}
Also used : FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Unavailability(org.cpsolver.studentsct.model.Unavailability) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Enrollment(org.cpsolver.studentsct.model.Enrollment) SctAssignment(org.cpsolver.studentsct.model.SctAssignment) HashSet(java.util.HashSet)

Example 4 with FreeTimeRequest

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

the class Test method section.

public boolean section(Student original) {
    OnlineSectioningModel model = new TestModel(iModel.getProperties());
    model.setOverExpectedCriterion(iModel.getOverExpectedCriterion());
    Student student = new Student(original.getId());
    Hashtable<CourseRequest, Set<Section>> preferredSectionsForCourse = new Hashtable<CourseRequest, Set<Section>>();
    Map<Long, Section> classTable = new HashMap<Long, Section>();
    synchronized (iModel) {
        for (Request request : original.getRequests()) {
            Request clonnedRequest = addRequest(student, original, request, classTable, model);
            Enrollment enrollment = assignment().getValue(request);
            if (enrollment != null && enrollment.isCourseRequest()) {
                Set<Section> sections = new HashSet<Section>();
                for (Section section : enrollment.getSections()) sections.add(classTable.get(section.getId()));
                preferredSectionsForCourse.put((CourseRequest) clonnedRequest, sections);
            }
        }
    }
    model.addStudent(student);
    model.setDistanceConflict(new DistanceConflict(iModel.getDistanceConflict().getDistanceMetric(), model.getProperties()));
    model.setTimeOverlaps(new TimeOverlapsCounter(null, model.getProperties()));
    for (LinkedSections link : iModel.getLinkedSections()) {
        List<Section> sections = new ArrayList<Section>();
        for (Offering offering : link.getOfferings()) for (Subpart subpart : link.getSubparts(offering)) for (Section section : link.getSections(subpart)) {
            Section x = classTable.get(section.getId());
            if (x != null)
                sections.add(x);
        }
        if (sections.size() >= 2)
            model.addLinkedSections(link.isMustBeUsed(), sections);
    }
    OnlineSectioningSelection selection = null;
    if (model.getProperties().getPropertyBoolean("StudentWeights.MultiCriteria", true)) {
        selection = new MultiCriteriaBranchAndBoundSelection(iModel.getProperties());
    } else {
        selection = new SuggestionSelection(model.getProperties());
    }
    selection.setModel(model);
    selection.setPreferredSections(preferredSectionsForCourse);
    selection.setRequiredSections(new Hashtable<CourseRequest, Set<Section>>());
    selection.setRequiredFreeTimes(new HashSet<FreeTimeRequest>());
    long t0 = JProf.currentTimeMillis();
    Assignment<Request, Enrollment> newAssignment = new AssignmentMap<Request, Enrollment>();
    BranchBoundNeighbour neighbour = selection.select(newAssignment, student);
    long time = JProf.currentTimeMillis() - t0;
    inc("[C] CPU Time", time);
    if (neighbour == null) {
        inc("[F] Failure");
    } else {
        if (iSuggestions) {
            StudentPreferencePenalties penalties = new StudentPreferencePenalties(StudentPreferencePenalties.sDistTypePreference);
            double maxOverExpected = 0;
            int assigned = 0;
            double penalty = 0.0;
            Hashtable<CourseRequest, Set<Section>> enrollments = new Hashtable<CourseRequest, Set<Section>>();
            List<RequestSectionPair> pairs = new ArrayList<RequestSectionPair>();
            for (int i = 0; i < neighbour.getAssignment().length; i++) {
                Enrollment enrl = neighbour.getAssignment()[i];
                if (enrl != null && enrl.isCourseRequest() && enrl.getAssignments() != null) {
                    assigned++;
                    for (Section section : enrl.getSections()) {
                        maxOverExpected += model.getOverExpected(newAssignment, section, enrl.getRequest());
                        pairs.add(new RequestSectionPair(enrl.variable(), section));
                    }
                    enrollments.put((CourseRequest) enrl.variable(), enrl.getSections());
                    penalty += penalties.getPenalty(enrl);
                }
            }
            penalty /= assigned;
            inc("[S] Initial Penalty", penalty);
            double nrSuggestions = 0.0, nrAccepted = 0.0, totalSuggestions = 0.0, nrTries = 0.0;
            for (int i = 0; i < pairs.size(); i++) {
                RequestSectionPair pair = pairs.get(i);
                SuggestionsBranchAndBound suggestionBaB = null;
                if (model.getProperties().getPropertyBoolean("StudentWeights.MultiCriteria", true)) {
                    suggestionBaB = new MultiCriteriaBranchAndBoundSuggestions(model.getProperties(), student, newAssignment, new Hashtable<CourseRequest, Set<Section>>(), new HashSet<FreeTimeRequest>(), enrollments, pair.getRequest(), pair.getSection(), null, maxOverExpected, iModel.getProperties().getPropertyBoolean("StudentWeights.PriorityWeighting", true));
                } else {
                    suggestionBaB = new SuggestionsBranchAndBound(model.getProperties(), student, newAssignment, new Hashtable<CourseRequest, Set<Section>>(), new HashSet<FreeTimeRequest>(), enrollments, pair.getRequest(), pair.getSection(), null, maxOverExpected);
                }
                long x0 = JProf.currentTimeMillis();
                TreeSet<SuggestionsBranchAndBound.Suggestion> suggestions = suggestionBaB.computeSuggestions();
                inc("[S] Suggestion CPU Time", JProf.currentTimeMillis() - x0);
                totalSuggestions += suggestions.size();
                if (!suggestions.isEmpty())
                    nrSuggestions += 1.0;
                nrTries += 1.0;
                SuggestionsBranchAndBound.Suggestion best = null;
                for (SuggestionsBranchAndBound.Suggestion suggestion : suggestions) {
                    int a = 0;
                    double p = 0.0;
                    for (int j = 0; j < suggestion.getEnrollments().length; j++) {
                        Enrollment e = suggestion.getEnrollments()[j];
                        if (e != null && e.isCourseRequest() && e.getAssignments() != null) {
                            p += penalties.getPenalty(e);
                            a++;
                        }
                    }
                    p /= a;
                    if (a > assigned || (assigned == a && p < penalty)) {
                        best = suggestion;
                    }
                }
                if (best != null) {
                    nrAccepted += 1.0;
                    Enrollment[] e = best.getEnrollments();
                    for (int j = 0; j < e.length; j++) if (e[j] != null && e[j].getAssignments() == null)
                        e[j] = null;
                    neighbour = new BranchBoundNeighbour(student, best.getValue(), e);
                    assigned = 0;
                    penalty = 0.0;
                    enrollments.clear();
                    pairs.clear();
                    for (int j = 0; j < neighbour.getAssignment().length; j++) {
                        Enrollment enrl = neighbour.getAssignment()[j];
                        if (enrl != null && enrl.isCourseRequest() && enrl.getAssignments() != null) {
                            assigned++;
                            for (Section section : enrl.getSections()) pairs.add(new RequestSectionPair(enrl.variable(), section));
                            enrollments.put((CourseRequest) enrl.variable(), enrl.getSections());
                            penalty += penalties.getPenalty(enrl);
                        }
                    }
                    penalty /= assigned;
                    inc("[S] Improved Penalty", penalty);
                }
            }
            inc("[S] Final Penalty", penalty);
            if (nrSuggestions > 0) {
                inc("[S] Classes with suggestion", nrSuggestions);
                inc("[S] Avg. # of suggestions", totalSuggestions / nrSuggestions);
                inc("[S] Suggestion acceptance rate [%]", nrAccepted / nrSuggestions);
            } else {
                inc("[S] Student with no suggestions available", 1.0);
            }
            if (!pairs.isEmpty())
                inc("[S] Probability that a class has suggestions [%]", nrSuggestions / nrTries);
        }
        List<Enrollment> enrollments = new ArrayList<Enrollment>();
        i: for (int i = 0; i < neighbour.getAssignment().length; i++) {
            Request request = original.getRequests().get(i);
            Enrollment clonnedEnrollment = neighbour.getAssignment()[i];
            if (clonnedEnrollment != null && clonnedEnrollment.getAssignments() != null) {
                if (request instanceof FreeTimeRequest) {
                    enrollments.add(((FreeTimeRequest) request).createEnrollment());
                } else {
                    for (Course course : ((CourseRequest) request).getCourses()) if (course.getId() == clonnedEnrollment.getCourse().getId())
                        for (Config config : course.getOffering().getConfigs()) if (config.getId() == clonnedEnrollment.getConfig().getId()) {
                            Set<Section> assignments = new HashSet<Section>();
                            for (Subpart subpart : config.getSubparts()) for (Section section : subpart.getSections()) {
                                if (clonnedEnrollment.getSections().contains(section)) {
                                    assignments.add(section);
                                }
                            }
                            Reservation reservation = null;
                            if (clonnedEnrollment.getReservation() != null) {
                                for (Reservation r : course.getOffering().getReservations()) if (r.getId() == clonnedEnrollment.getReservation().getId()) {
                                    reservation = r;
                                    break;
                                }
                            }
                            enrollments.add(new Enrollment(request, clonnedEnrollment.getPriority(), course, config, assignments, reservation));
                            continue i;
                        }
                }
            }
        }
        synchronized (iModel) {
            for (Request r : original.getRequests()) {
                Enrollment e = assignment().getValue(r);
                r.setInitialAssignment(e);
                if (e != null)
                    updateSpace(assignment(), e, true);
            }
            for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
                assignment().unassign(0, r);
            boolean fail = false;
            for (Enrollment enrl : enrollments) {
                if (iModel.conflictValues(assignment(), enrl).isEmpty()) {
                    assignment().assign(0, enrl);
                } else {
                    fail = true;
                    break;
                }
            }
            if (fail) {
                for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
                    assignment().unassign(0, r);
                for (Request r : original.getRequests()) if (r.getInitialAssignment() != null)
                    assignment().assign(0, r.getInitialAssignment());
                for (Request r : original.getRequests()) if (assignment().getValue(r) != null)
                    updateSpace(assignment(), assignment().getValue(r), false);
            } else {
                for (Enrollment enrl : enrollments) updateSpace(assignment(), enrl, false);
            }
            if (fail)
                return false;
        }
        neighbour.assign(newAssignment, 0);
        int a = 0, u = 0, np = 0, zp = 0, pp = 0, cp = 0;
        double over = 0;
        double p = 0.0;
        for (Request r : student.getRequests()) {
            if (r instanceof CourseRequest) {
                Enrollment e = newAssignment.getValue(r);
                if (e != null) {
                    for (Section s : e.getSections()) {
                        if (s.getPenalty() < 0.0)
                            np++;
                        if (s.getPenalty() == 0.0)
                            zp++;
                        if (s.getPenalty() > 0.0)
                            pp++;
                        if (s.getLimit() > 0) {
                            p += s.getPenalty();
                            cp++;
                        }
                        over += model.getOverExpected(newAssignment, s, r);
                    }
                    a++;
                } else {
                    u++;
                }
            }
        }
        inc("[A] Student");
        if (over > 0.0)
            inc("[O] Over", over);
        if (a > 0)
            inc("[A] Assigned", a);
        if (u > 0)
            inc("[A] Not Assigned", u);
        inc("[V] Value", neighbour.value(newAssignment));
        if (zp > 0)
            inc("[P] Zero penalty", zp);
        if (np > 0)
            inc("[P] Negative penalty", np);
        if (pp > 0)
            inc("[P] Positive penalty", pp);
        if (cp > 0)
            inc("[P] Average penalty", p / cp);
    }
    inc("[T0] Time <10ms", time < 10 ? 1 : 0);
    inc("[T1] Time <100ms", time < 100 ? 1 : 0);
    inc("[T2] Time <250ms", time < 250 ? 1 : 0);
    inc("[T3] Time <500ms", time < 500 ? 1 : 0);
    inc("[T4] Time <1s", time < 1000 ? 1 : 0);
    inc("[T5] Time >=1s", time >= 1000 ? 1 : 0);
    return true;
}
Also used : StudentPreferencePenalties(org.cpsolver.studentsct.StudentPreferencePenalties) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) HashMap(java.util.HashMap) Config(org.cpsolver.studentsct.model.Config) DistanceConflict(org.cpsolver.studentsct.extension.DistanceConflict) ArrayList(java.util.ArrayList) SuggestionSelection(org.cpsolver.studentsct.online.selection.SuggestionSelection) CourseReservation(org.cpsolver.studentsct.reservation.CourseReservation) Reservation(org.cpsolver.studentsct.reservation.Reservation) LinkedSections(org.cpsolver.studentsct.constraint.LinkedSections) Enrollment(org.cpsolver.studentsct.model.Enrollment) SuggestionsBranchAndBound(org.cpsolver.studentsct.online.selection.SuggestionsBranchAndBound) Course(org.cpsolver.studentsct.model.Course) HashSet(java.util.HashSet) MultiCriteriaBranchAndBoundSelection(org.cpsolver.studentsct.online.selection.MultiCriteriaBranchAndBoundSelection) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Hashtable(java.util.Hashtable) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Student(org.cpsolver.studentsct.model.Student) OnlineSectioningSelection(org.cpsolver.studentsct.online.selection.OnlineSectioningSelection) Section(org.cpsolver.studentsct.model.Section) Offering(org.cpsolver.studentsct.model.Offering) TimeOverlapsCounter(org.cpsolver.studentsct.extension.TimeOverlapsCounter) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) AssignmentMap(org.cpsolver.ifs.assignment.AssignmentMap) BranchBoundNeighbour(org.cpsolver.studentsct.heuristics.selection.BranchBoundSelection.BranchBoundNeighbour) Subpart(org.cpsolver.studentsct.model.Subpart) MultiCriteriaBranchAndBoundSuggestions(org.cpsolver.studentsct.online.selection.MultiCriteriaBranchAndBoundSuggestions)

Example 5 with FreeTimeRequest

use of org.cpsolver.studentsct.model.FreeTimeRequest 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;
    for (int idx = 0; idx < current.length; idx++) {
        if (isFreeTime(idx)) {
            ft = true;
            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;
            }
        }
    }
    // 0.5. avoid course time overlaps & unavailability overlaps
    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, section, best[idx].getRequest());
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) currentPenalties += getModel().getOverExpected(assignment, 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].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 instanceof CourseRequest && !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;
                }
            }
        }
    }
    // 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;
    // 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) {
                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) {
                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 sections
    int bestNoTime = 0, currentNoTime = 0;
    for (int idx = 0; idx < current.length; idx++) {
        if (best[idx] != null) {
            for (Section section : best[idx].getSections()) if (section.getTime() == null)
                bestNoTime++;
        }
        if (current[idx] != null && idx < maxIdx) {
            for (Section section : current[idx].getSections()) if (section.getTime() == null)
                currentNoTime++;
        }
    }
    if (currentNoTime < bestNoTime)
        return true;
    if (bestNoTime < currentNoTime)
        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();
            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();
        }
    }
    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) 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

FreeTimeRequest (org.cpsolver.studentsct.model.FreeTimeRequest)14 CourseRequest (org.cpsolver.studentsct.model.CourseRequest)11 Section (org.cpsolver.studentsct.model.Section)11 Request (org.cpsolver.studentsct.model.Request)9 Enrollment (org.cpsolver.studentsct.model.Enrollment)8 HashSet (java.util.HashSet)7 ArrayList (java.util.ArrayList)6 Course (org.cpsolver.studentsct.model.Course)6 HashMap (java.util.HashMap)5 TreeSet (java.util.TreeSet)5 Subpart (org.cpsolver.studentsct.model.Subpart)5 Map (java.util.Map)4 Set (java.util.Set)4 Comparator (java.util.Comparator)3 CSVFile (org.cpsolver.ifs.util.CSVFile)3 Student (org.cpsolver.studentsct.model.Student)3 CourseReservation (org.cpsolver.studentsct.reservation.CourseReservation)2 Reservation (org.cpsolver.studentsct.reservation.Reservation)2 Element (org.dom4j.Element)2 Hashtable (java.util.Hashtable)1