Search in sources :

Example 31 with Request

use of org.cpsolver.studentsct.model.Request 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) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) List(java.util.List) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 32 with Request

use of org.cpsolver.studentsct.model.Request 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 (!request.isAlternative() || iCurrentAssignment[idx] != null)
        return true;
    int alt = 0;
    int i = 0;
    for (Iterator<Request> e = iStudent.getRequests().iterator(); e.hasNext(); i++) {
        Request r = e.next();
        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 (alt > 0);
}
Also used : CourseRequest(org.cpsolver.studentsct.model.CourseRequest) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 33 with Request

use of org.cpsolver.studentsct.model.Request 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)

Example 34 with Request

use of org.cpsolver.studentsct.model.Request 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)

Example 35 with Request

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

the class ShuffleStudentsSelection method selectNeighbour.

@Override
public Neighbour<Request, Enrollment> selectNeighbour(Solution<Request, Enrollment> solution) {
    Shuffle shuffle = null;
    while ((shuffle = iQueue.poll()) != null) {
        Progress.getInstance(solution.getModel()).incProgress();
        // Take an item from the queue, try backtrack first
        Neighbour<Request, Enrollment> n = iBacktrack.selectNeighbour(solution, shuffle);
        if (n != null)
            return n;
        // If fails, just assign the request randomly and hope for the best
        List<Enrollment> adepts = new ArrayList<Enrollment>();
        for (Enrollment e : shuffle.getRequest().values(solution.getAssignment())) {
            if (shuffle.matchFilter(e))
                adepts.add(e);
        }
        if (!adepts.isEmpty()) {
            return new SimpleNeighbour<Request, Enrollment>(shuffle.getRequest(), ToolBox.random(adepts));
        }
    }
    return null;
}
Also used : SimpleNeighbour(org.cpsolver.ifs.model.SimpleNeighbour) Request(org.cpsolver.studentsct.model.Request) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) ArrayList(java.util.ArrayList) Enrollment(org.cpsolver.studentsct.model.Enrollment)

Aggregations

Request (org.cpsolver.studentsct.model.Request)65 CourseRequest (org.cpsolver.studentsct.model.CourseRequest)51 Enrollment (org.cpsolver.studentsct.model.Enrollment)47 FreeTimeRequest (org.cpsolver.studentsct.model.FreeTimeRequest)23 Section (org.cpsolver.studentsct.model.Section)22 ArrayList (java.util.ArrayList)21 Student (org.cpsolver.studentsct.model.Student)21 Course (org.cpsolver.studentsct.model.Course)20 HashSet (java.util.HashSet)18 HashMap (java.util.HashMap)14 Subpart (org.cpsolver.studentsct.model.Subpart)10 Map (java.util.Map)9 DataProperties (org.cpsolver.ifs.util.DataProperties)9 Config (org.cpsolver.studentsct.model.Config)8 Offering (org.cpsolver.studentsct.model.Offering)8 Set (java.util.Set)7 DefaultSingleAssignment (org.cpsolver.ifs.assignment.DefaultSingleAssignment)7 File (java.io.File)6 IOException (java.io.IOException)6 TreeSet (java.util.TreeSet)6