Search in sources :

Example 11 with Subpart

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

the class LinkedSections method computeConflicts.

/**
 * Compute conflicting enrollments. If the given enrollment contains sections of this link
 * (one for each subpart in {@link LinkedSections#getSubparts(Offering)}), another assignment
 * of this student is in a conflict, if it does not contain the appropriate sections from
 * {@link LinkedSections#getSubparts(Offering)} and {@link LinkedSections#getSections(Subpart)}.
 *
 * @param enrollment given enrollment
 * @param assignment custom assignment
 * @param conflicts found conflicts are given to this interface, see {@link ConflictHandler#onConflict(Enrollment)}
 */
public void computeConflicts(Enrollment enrollment, EnrollmentAssignment assignment, ConflictHandler conflicts) {
    if (enrollment == null || enrollment.getCourse() == null)
        return;
    if (enrollment.getReservation() != null && enrollment.getReservation().canBreakLinkedSections())
        return;
    Map<Subpart, Set<Section>> subparts = iSections.get(enrollment.getCourse().getOffering());
    if (subparts == null || subparts.isEmpty())
        return;
    boolean match = false, partial = false;
    for (Section section : enrollment.getSections()) {
        Set<Section> sections = subparts.get(section.getSubpart());
        if (sections != null) {
            if (sections.contains(section))
                match = true;
            else
                partial = true;
        }
    }
    boolean full = match && !partial;
    if (isMustBeUsed()) {
        if (!full) {
            // not full match -> conflict if there is no other linked section constraint with a full match
            // check if there is some other constraint taking care of this case
            boolean hasOtherMatch = false;
            for (LinkedSections other : enrollment.getStudent().getLinkedSections()) {
                if (other.hasFullMatch(enrollment) && nrSharedOfferings(other) > 1) {
                    hasOtherMatch = true;
                    break;
                }
            }
            // no other match -> problem
            if (!hasOtherMatch && !conflicts.onConflict(enrollment))
                return;
        }
    }
    if (full) {
        // full match -> check other enrollments
        for (int i = 0; i < enrollment.getStudent().getRequests().size(); i++) {
            Request request = enrollment.getStudent().getRequests().get(i);
            // given enrollment
            if (request.equals(enrollment.getRequest()))
                continue;
            Enrollment otherEnrollment = assignment.getEnrollment(request, i);
            // not assigned or not course request
            if (otherEnrollment == null || otherEnrollment.getCourse() == null)
                continue;
            if (otherEnrollment.getReservation() != null && otherEnrollment.getReservation().canBreakLinkedSections())
                continue;
            Map<Subpart, Set<Section>> otherSubparts = iSections.get(otherEnrollment.getCourse().getOffering());
            // offering is not in the link
            if (otherSubparts == null || otherSubparts.isEmpty())
                continue;
            boolean otherMatch = false, otherPartial = false;
            for (Section section : otherEnrollment.getSections()) {
                Set<Section> otherSections = otherSubparts.get(section.getSubpart());
                if (otherSections != null) {
                    if (otherSections.contains(section))
                        otherMatch = true;
                    else
                        otherPartial = true;
                }
            }
            boolean otherFull = otherMatch && !otherPartial;
            // not full match -> conflict
            if (!otherFull && !conflicts.onConflict(otherEnrollment))
                return;
        }
    } else {
        // no or only partial match -> there should be no match in other offerings too
        for (int i = 0; i < enrollment.getStudent().getRequests().size(); i++) {
            Request request = enrollment.getStudent().getRequests().get(i);
            // given enrollment
            if (request.equals(enrollment.getRequest()))
                continue;
            Enrollment otherEnrollment = assignment.getEnrollment(request, i);
            // not assigned or not course request
            if (otherEnrollment == null || otherEnrollment.getCourse() == null)
                continue;
            if (otherEnrollment.getReservation() != null && otherEnrollment.getReservation().canBreakLinkedSections())
                continue;
            Map<Subpart, Set<Section>> otherSubparts = iSections.get(otherEnrollment.getCourse().getOffering());
            // offering is not in the link
            if (otherSubparts == null || otherSubparts.isEmpty())
                continue;
            boolean otherMatch = false, otherPartial = false;
            for (Section section : otherEnrollment.getSections()) {
                Set<Section> otherSections = otherSubparts.get(section.getSubpart());
                if (otherSections != null) {
                    if (otherSections.contains(section))
                        otherMatch = true;
                    else
                        otherPartial = true;
                }
            }
            boolean otherFull = otherMatch && !otherPartial;
            // full match -> conflict
            if (otherFull && !conflicts.onConflict(otherEnrollment))
                return;
        }
    }
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Subpart(org.cpsolver.studentsct.model.Subpart) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Request(org.cpsolver.studentsct.model.Request) Enrollment(org.cpsolver.studentsct.model.Enrollment) Section(org.cpsolver.studentsct.model.Section) Constraint(org.cpsolver.ifs.model.Constraint)

Example 12 with Subpart

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

the class LinkedSections method hasFullMatch.

/**
 * Check if the given enrollment fully matches this constraint
 * @param enrollment an enrollment
 * @return true, if there is a full match
 */
protected boolean hasFullMatch(Enrollment enrollment) {
    // not assigned or not course request
    if (enrollment == null || enrollment.getCourse() == null)
        return false;
    Map<Subpart, Set<Section>> subparts = iSections.get(enrollment.getCourse().getOffering());
    // offering is not in the link
    if (subparts == null || subparts.isEmpty())
        return false;
    boolean match = false, partial = false;
    for (Section section : enrollment.getSections()) {
        Set<Section> sections = subparts.get(section.getSubpart());
        if (sections != null) {
            if (sections.contains(section))
                match = true;
            else
                partial = true;
        }
    }
    return match && !partial;
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Subpart(org.cpsolver.studentsct.model.Subpart) Section(org.cpsolver.studentsct.model.Section)

Example 13 with Subpart

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

the class LinkedSections method toString.

@Override
public String toString() {
    String sections = "";
    for (Map.Entry<Offering, Map<Subpart, Set<Section>>> e : iSections.entrySet()) {
        sections += (sections.isEmpty() ? "" : "; ") + e.getKey().getName();
        Set<String> ids = new TreeSet<String>();
        for (Map.Entry<Subpart, Set<Section>> f : e.getValue().entrySet()) {
            for (Section s : f.getValue()) ids.add(s.getName());
            sections += ":" + ids;
        }
    }
    return "LinkedSections{" + sections + "}";
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) TreeSet(java.util.TreeSet) Subpart(org.cpsolver.studentsct.model.Subpart) HashMap(java.util.HashMap) Map(java.util.Map) Offering(org.cpsolver.studentsct.model.Offering) Section(org.cpsolver.studentsct.model.Section)

Example 14 with Subpart

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

the class OnlineSelection method setPenalties.

/**
 * Set online sectioning penalties to all sections of all courses of the
 * given student
 */
private static void setPenalties(Assignment<Request, Enrollment> assignment, Student student) {
    for (Request request : student.getRequests()) {
        if (!(request instanceof CourseRequest))
            continue;
        CourseRequest courseRequest = (CourseRequest) request;
        for (Course course : courseRequest.getCourses()) {
            for (Config config : course.getOffering().getConfigs()) {
                for (Subpart subpart : config.getSubparts()) {
                    for (Section section : subpart.getSections()) {
                        section.setPenalty(section.getOnlineSectioningPenalty(assignment));
                    }
                }
            }
        }
        courseRequest.clearCache();
    }
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Config(org.cpsolver.studentsct.model.Config) Subpart(org.cpsolver.studentsct.model.Subpart) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Request(org.cpsolver.studentsct.model.Request) Course(org.cpsolver.studentsct.model.Course) Section(org.cpsolver.studentsct.model.Section)

Example 15 with Subpart

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

the class ShuffleStudentsSelection method init.

@Override
public void init(Solver<Request, Enrollment> solver) {
    StudentSectioningModel model = (StudentSectioningModel) solver.currentSolution().getModel();
    iQueue = new LinkedList<Shuffle>();
    Assignment<Request, Enrollment> assignment = solver.currentSolution().getAssignment();
    // Check all request groups that have a spread < 1.0
    RouletteWheelSelection<RequestGroup> groups = new RouletteWheelSelection<RequestGroup>();
    for (Offering offering : model.getOfferings()) {
        for (Course course : offering.getCourses()) {
            for (RequestGroup group : course.getRequestGroups()) {
                double spread = group.getAverageSpread(solver.currentSolution().getAssignment());
                if (spread >= 1.0)
                    continue;
                groups.add(group, 1.0 - spread);
            }
        }
    }
    // If there are some, pick one randomly (using roulette wheel selection)
    if (groups.hasMoreElements()) {
        RequestGroup group = groups.nextElement();
        RouletteWheelSelection<Subpart> subparts = new RouletteWheelSelection<Subpart>();
        for (CourseRequest cr : group.getRequests()) {
            Enrollment e = assignment.getValue(cr);
            if (e != null)
                for (Section section : e.getSections()) if (group.getSectionSpread(assignment, section) < 1.0)
                    subparts.addExisting(section.getSubpart(), 1.0);
        }
        if (subparts.hasMoreElements()) {
            // Pick a subpart that has sections with a section spread < 1.0
            Subpart subpart = subparts.nextElement();
            RouletteWheelSelection<Section> sections = new RouletteWheelSelection<Section>();
            section: for (Section section : subpart.getSections()) {
                // Only take sections that all requests can use
                for (CourseRequest cr : group.getRequests()) {
                    boolean match = false;
                    for (Enrollment e : cr.values(assignment)) if (e.getSections().contains(section)) {
                        match = true;
                        break;
                    }
                    if (!match)
                        continue section;
                }
                // Take sections with conflicts with lower probability
                int nrConflicts = 0;
                if (!section.isAllowOverlap())
                    requests: for (CourseRequest cr : group.getRequests()) {
                        for (Request r : cr.getStudent().getRequests()) {
                            if (r.equals(cr))
                                continue;
                            Enrollment e = assignment.getValue(r);
                            if (e != null && !e.isAllowOverlap() && section.isOverlapping(e.getSections())) {
                                nrConflicts++;
                                continue requests;
                            }
                        }
                    }
                sections.add(section, 1 + group.getRequests().size() - nrConflicts);
            }
            Set<Section> filter = new HashSet<Section>();
            double space = 0.0;
            // Pick enough sections
            while (sections.hasMoreElements()) {
                Section section = sections.nextElement();
                if (filter.add(section)) {
                    if (section.getLimit() < 0)
                        break;
                    space += section.getLimit();
                }
                if (space >= group.getTotalWeight())
                    break;
            }
            // Add all requests that should be moved into the queue
            for (CourseRequest cr : group.getRequests()) {
                Shuffle shuffle = new Shuffle(group, cr, filter);
                Enrollment e = assignment.getValue(cr);
                if (e != null && shuffle.matchFilter(e))
                    continue;
                iQueue.add(shuffle);
            }
        } else {
            // No subpart -> no section filter
            for (CourseRequest cr : group.getRequests()) iQueue.add(new Shuffle(group, cr, null));
        }
    }
    // Shuffle the queue
    Collections.shuffle((LinkedList<Shuffle>) iQueue);
    // Initialize the backtrack selection, if needed
    if (iBacktrack == null) {
        try {
            iBacktrack = new ShuffleBacktrackNeighbourSelection(solver.getProperties());
            iBacktrack.init(solver);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
    // Change progress
    Progress.getInstance(solver.currentSolution().getModel()).setPhase("Shuffling students along request groups...", iQueue.size());
}
Also used : RouletteWheelSelection(org.cpsolver.ifs.heuristics.RouletteWheelSelection) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) Offering(org.cpsolver.studentsct.model.Offering) Section(org.cpsolver.studentsct.model.Section) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) RequestGroup(org.cpsolver.studentsct.model.RequestGroup) Subpart(org.cpsolver.studentsct.model.Subpart) Enrollment(org.cpsolver.studentsct.model.Enrollment) Course(org.cpsolver.studentsct.model.Course) StudentSectioningModel(org.cpsolver.studentsct.StudentSectioningModel) HashSet(java.util.HashSet)

Aggregations

Subpart (org.cpsolver.studentsct.model.Subpart)44 Section (org.cpsolver.studentsct.model.Section)40 Config (org.cpsolver.studentsct.model.Config)23 CourseRequest (org.cpsolver.studentsct.model.CourseRequest)22 Offering (org.cpsolver.studentsct.model.Offering)16 Course (org.cpsolver.studentsct.model.Course)13 Request (org.cpsolver.studentsct.model.Request)13 HashSet (java.util.HashSet)12 Set (java.util.Set)12 TreeSet (java.util.TreeSet)10 Enrollment (org.cpsolver.studentsct.model.Enrollment)10 Map (java.util.Map)8 Element (org.dom4j.Element)7 HashMap (java.util.HashMap)6 FreeTimeRequest (org.cpsolver.studentsct.model.FreeTimeRequest)6 Student (org.cpsolver.studentsct.model.Student)6 BitSet (java.util.BitSet)5 DistanceConflict (org.cpsolver.studentsct.extension.DistanceConflict)5 StudentQuality (org.cpsolver.studentsct.extension.StudentQuality)5 TimeOverlapsCounter (org.cpsolver.studentsct.extension.TimeOverlapsCounter)5