Search in sources :

Example 1 with GlobalConstraint

use of org.cpsolver.ifs.model.GlobalConstraint in project cpsolver by UniTime.

the class CourseConflictTable method createTable.

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

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

Example 2 with GlobalConstraint

use of org.cpsolver.ifs.model.GlobalConstraint in project cpsolver by UniTime.

the class GroupConstraint method forwardCheck.

public boolean forwardCheck(Assignment<Lecture, Placement> assignment, Placement value, Set<GroupConstraint> ignore, int depth) {
    try {
        if (depth < 0)
            return true;
        ignore.add(this);
        int neededSize = value.variable().maxRoomUse();
        for (Lecture lecture : variables()) {
            // Skip this lecture
            if (lecture.equals(value.variable()))
                continue;
            Placement current = assignment.getValue(lecture);
            if (current != null) {
                // Has assignment, check whether it is conflicting
                if (isSatisfiedPair(assignment, value, current)) {
                    // Increase needed size if the assignment is of the same room and overlapping in time
                    if (canShareRoom() && sameRoomAndOverlaps(value, current)) {
                        neededSize += lecture.maxRoomUse();
                    }
                    continue;
                }
                return false;
            }
            // Look for supporting assignments assignment
            boolean shareRoomAndOverlaps = canShareRoom();
            Placement support = null;
            int nrSupports = 0;
            if (lecture.nrValues() >= iForwardCheckMaxDomainSize) {
                // ignore variables with large domains
                return true;
            }
            List<Placement> values = lecture.values(assignment);
            if (values.isEmpty()) {
                // ignore variables with empty domain
                return true;
            }
            for (Placement other : lecture.values(assignment)) {
                if (nrSupports < 2) {
                    if (isSatisfiedPair(assignment, value, other)) {
                        if (support == null)
                            support = other;
                        nrSupports++;
                        if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other))
                            shareRoomAndOverlaps = false;
                    }
                } else if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other) && isSatisfiedPair(assignment, value, other)) {
                    shareRoomAndOverlaps = false;
                }
                if (nrSupports > 1 && !shareRoomAndOverlaps)
                    break;
            }
            // No supporting assignment -> fail
            if (nrSupports == 0) {
                // other class cannot be assigned with this value
                return false;
            }
            // Increase needed size if all supporters are of the same room and in overlapping times
            if (shareRoomAndOverlaps) {
                neededSize += lecture.maxRoomUse();
            }
            // Only one supporter -> propagate the new assignment over other hard constraints of the lecture
            if (nrSupports == 1) {
                for (Constraint<Lecture, Placement> other : lecture.hardConstraints()) {
                    if (other instanceof WeakeningConstraint)
                        continue;
                    if (other instanceof GroupConstraint) {
                        GroupConstraint gc = (GroupConstraint) other;
                        if (depth > 0 && !ignore.contains(gc) && !gc.forwardCheck(assignment, support, ignore, depth - 1))
                            return false;
                    } else {
                        if (other.inConflict(assignment, support))
                            return false;
                    }
                }
                for (GlobalConstraint<Lecture, Placement> other : getModel().globalConstraints()) {
                    if (other instanceof WeakeningConstraint)
                        continue;
                    if (other.inConflict(assignment, support))
                        return false;
                }
            }
        }
        if (canShareRoom() && neededSize > value.getRoomSize()) {
            // room is too small to fit all meet with classes
            return false;
        }
        return true;
    } finally {
        ignore.remove(this);
    }
}
Also used : Lecture(org.cpsolver.coursett.model.Lecture) Placement(org.cpsolver.coursett.model.Placement) WeakeningConstraint(org.cpsolver.ifs.model.WeakeningConstraint) WeakeningConstraint(org.cpsolver.ifs.model.WeakeningConstraint) Constraint(org.cpsolver.ifs.model.Constraint) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 3 with GlobalConstraint

use of org.cpsolver.ifs.model.GlobalConstraint in project cpsolver by UniTime.

the class GroupConstraint method forwardCheck.

public void forwardCheck(Assignment<Lecture, Placement> assignment, Placement value, Set<Placement> conflicts, Set<GroupConstraint> ignore, int depth) {
    try {
        if (depth < 0)
            return;
        ignore.add(this);
        List<Placement> neededSize = null;
        for (Lecture lecture : variables()) {
            // already conflicting
            if (conflicts.contains(value))
                break;
            // Skip this lecture
            if (lecture.equals(value.variable()))
                continue;
            Placement current = assignment.getValue(lecture);
            if (current != null) {
                // Has assignment, check whether it is conflicting
                if (isSatisfiedPair(assignment, value, current)) {
                    // Increase needed size if the assignment is of the same room and overlapping in time
                    if (canShareRoom() && sameRoomAndOverlaps(value, current)) {
                        if (neededSize == null)
                            neededSize = new ArrayList<Placement>();
                        neededSize.add(current);
                    }
                    continue;
                }
                conflicts.add(current);
            }
            // Look for supporting assignments assignment
            boolean shareRoomAndOverlaps = canShareRoom();
            Placement support = null;
            int nrSupports = 0;
            if (lecture.nrValues() >= iForwardCheckMaxDomainSize) {
                // ignore variables with large domains
                return;
            }
            List<Placement> values = lecture.values(assignment);
            if (values.isEmpty()) {
                // ignore variables with empty domain
                return;
            }
            for (Placement other : values) {
                if (nrSupports < 2) {
                    if (isSatisfiedPair(assignment, value, other)) {
                        if (support == null)
                            support = other;
                        nrSupports++;
                        if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other))
                            shareRoomAndOverlaps = false;
                    }
                } else if (shareRoomAndOverlaps && !sameRoomAndOverlaps(value, other) && isSatisfiedPair(assignment, value, other)) {
                    shareRoomAndOverlaps = false;
                }
                if (nrSupports > 1 && !shareRoomAndOverlaps)
                    break;
            }
            // No supporting assignment -> fail
            if (nrSupports == 0) {
                // other class cannot be assigned with this value
                conflicts.add(value);
                return;
            }
            // Increase needed size if all supporters are of the same room and in overlapping times
            if (shareRoomAndOverlaps && support != null) {
                if (neededSize == null)
                    neededSize = new ArrayList<Placement>();
                neededSize.add(support);
            }
            // Only one supporter -> propagate the new assignment over other hard constraints of the lecture
            if (nrSupports == 1) {
                for (Constraint<Lecture, Placement> other : lecture.hardConstraints()) {
                    if (other instanceof WeakeningConstraint)
                        continue;
                    if (other instanceof GroupConstraint) {
                        GroupConstraint gc = (GroupConstraint) other;
                        if (depth > 0 && !ignore.contains(gc))
                            gc.forwardCheck(assignment, support, conflicts, ignore, depth - 1);
                    } else {
                        other.computeConflicts(assignment, support, conflicts);
                    }
                }
                for (GlobalConstraint<Lecture, Placement> other : getModel().globalConstraints()) {
                    if (other instanceof WeakeningConstraint)
                        continue;
                    other.computeConflicts(assignment, support, conflicts);
                }
                if (conflicts.contains(support))
                    conflicts.add(value);
            }
        }
        if (canShareRoom() && neededSize != null) {
            if (value.getRoomLocations() != null) {
                for (RoomLocation room : value.getRoomLocations()) if (room.getRoomConstraint() != null && !room.getRoomConstraint().checkRoomSize(value, neededSize)) {
                    // room is too small to fit all meet with classes
                    conflicts.add(value);
                }
            } else if (value.getRoomLocation() != null) {
                RoomLocation room = value.getRoomLocation();
                if (room.getRoomConstraint() != null && !room.getRoomConstraint().checkRoomSize(value, neededSize)) {
                    // room is too small to fit all meet with classes
                    conflicts.add(value);
                }
            }
        }
    } finally {
        ignore.remove(this);
    }
}
Also used : Lecture(org.cpsolver.coursett.model.Lecture) Placement(org.cpsolver.coursett.model.Placement) RoomLocation(org.cpsolver.coursett.model.RoomLocation) ArrayList(java.util.ArrayList) WeakeningConstraint(org.cpsolver.ifs.model.WeakeningConstraint) WeakeningConstraint(org.cpsolver.ifs.model.WeakeningConstraint) Constraint(org.cpsolver.ifs.model.Constraint) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint)

Example 4 with GlobalConstraint

use of org.cpsolver.ifs.model.GlobalConstraint in project cpsolver by UniTime.

the class SectionConflictTable method createTable.

/**
 * Create report
 *
 * @param assignment current assignment
 * @param includeLastLikeStudents
 *            true, if last-like students should be included (i.e.,
 *            {@link Student#isDummy()} is true)
 * @param includeRealStudents
 *            true, if real students should be included (i.e.,
 *            {@link Student#isDummy()} is false)
 * @param useAmPm use 12-hour format
 * @return report as comma separated text file
 */
public CSVFile createTable(Assignment<Request, Enrollment> assignment, boolean includeLastLikeStudents, boolean includeRealStudents, boolean useAmPm) {
    HashMap<Course, Map<Section, Double[]>> unavailabilities = new HashMap<Course, Map<Section, Double[]>>();
    HashMap<Course, Set<Long>> totals = new HashMap<Course, Set<Long>>();
    HashMap<CourseSection, Map<CourseSection, Double>> conflictingPairs = new HashMap<CourseSection, Map<CourseSection, Double>>();
    HashMap<CourseSection, Double> sectionOverlaps = new HashMap<CourseSection, Double>();
    for (Request request : new ArrayList<Request>(getModel().unassignedVariables(assignment))) {
        if (request.getStudent().isDummy() && !includeLastLikeStudents)
            continue;
        if (!request.getStudent().isDummy() && !includeRealStudents)
            continue;
        if (request instanceof CourseRequest) {
            CourseRequest courseRequest = (CourseRequest) request;
            if (courseRequest.getStudent().isComplete(assignment))
                continue;
            List<Enrollment> values = courseRequest.values(assignment);
            SectionLimit limitConstraint = null;
            for (GlobalConstraint<Request, Enrollment> c : getModel().globalConstraints()) {
                if (c instanceof SectionLimit) {
                    limitConstraint = (SectionLimit) c;
                    break;
                }
            }
            if (limitConstraint == null) {
                limitConstraint = new SectionLimit(new DataProperties());
                limitConstraint.setModel(getModel());
            }
            List<Enrollment> notAvailableValues = new ArrayList<Enrollment>(values.size());
            List<Enrollment> availableValues = new ArrayList<Enrollment>(values.size());
            for (Enrollment enrollment : values) {
                if (limitConstraint.inConflict(assignment, enrollment))
                    notAvailableValues.add(enrollment);
                else
                    availableValues.add(enrollment);
            }
            if (!notAvailableValues.isEmpty() && iType.hasUnavailabilities()) {
                List<Enrollment> notOverlappingEnrollments = new ArrayList<Enrollment>(values.size());
                enrollments: for (Enrollment enrollment : notAvailableValues) {
                    for (Request other : request.getStudent().getRequests()) {
                        if (other.equals(request) || assignment.getValue(other) == null || other instanceof FreeTimeRequest)
                            continue;
                        if (assignment.getValue(other).isOverlapping(enrollment))
                            continue enrollments;
                    }
                    // not overlapping
                    notOverlappingEnrollments.add(enrollment);
                }
                if (notOverlappingEnrollments.isEmpty() && availableValues.isEmpty() && iOverlapsAllEnrollments) {
                    double fraction = request.getWeight() / notAvailableValues.size();
                    Set<CourseSection> ones = new HashSet<CourseSection>();
                    for (Enrollment enrollment : notAvailableValues) {
                        boolean hasConflict = false;
                        for (Section s : enrollment.getSections()) {
                            if (s.getLimit() >= 0 && s.getEnrollmentWeight(assignment, request) + request.getWeight() > s.getLimit()) {
                                hasConflict = true;
                                break;
                            }
                        }
                        Map<Section, Double[]> sections = unavailabilities.get(enrollment.getCourse());
                        if (sections == null) {
                            sections = new HashMap<Section, Double[]>();
                            unavailabilities.put(enrollment.getCourse(), sections);
                        }
                        for (Section s : enrollment.getSections()) {
                            if (hasConflict && s.getLimit() < 0 || s.getEnrollmentWeight(assignment, request) + request.getWeight() <= s.getLimit())
                                continue;
                            Double[] total = sections.get(s);
                            sections.put(s, new Double[] { fraction + (total == null ? 0.0 : total[0].doubleValue()), (total == null ? 0.0 : total[1].doubleValue()) });
                            ones.add(new CourseSection(enrollment.getCourse(), s));
                        }
                        Set<Long> total = totals.get(enrollment.getCourse());
                        if (total == null) {
                            total = new HashSet<Long>();
                            totals.put(enrollment.getCourse(), total);
                        }
                        total.add(enrollment.getStudent().getId());
                    }
                } else if (!notOverlappingEnrollments.isEmpty()) {
                    double fraction = request.getWeight() / notOverlappingEnrollments.size();
                    Set<CourseSection> ones = new HashSet<CourseSection>();
                    for (Enrollment enrollment : notOverlappingEnrollments) {
                        boolean hasConflict = false;
                        for (Section s : enrollment.getSections()) {
                            if (s.getLimit() >= 0 && s.getEnrollmentWeight(assignment, request) + request.getWeight() > s.getLimit()) {
                                hasConflict = true;
                                break;
                            }
                        }
                        Map<Section, Double[]> sections = unavailabilities.get(enrollment.getCourse());
                        if (sections == null) {
                            sections = new HashMap<Section, Double[]>();
                            unavailabilities.put(enrollment.getCourse(), sections);
                        }
                        for (Section s : enrollment.getSections()) {
                            if (hasConflict && s.getLimit() < 0 || s.getEnrollmentWeight(assignment, request) + request.getWeight() <= s.getLimit())
                                continue;
                            Double[] total = sections.get(s);
                            sections.put(s, new Double[] { fraction + (total == null ? 0.0 : total[0].doubleValue()), (total == null ? 0.0 : total[1].doubleValue()) });
                            ones.add(new CourseSection(enrollment.getCourse(), s));
                        }
                        Set<Long> total = totals.get(enrollment.getCourse());
                        if (total == null) {
                            total = new HashSet<Long>();
                            totals.put(enrollment.getCourse(), total);
                        }
                        total.add(enrollment.getStudent().getId());
                    }
                    for (CourseSection section : ones) {
                        Map<Section, Double[]> sections = unavailabilities.get(section.getCourse());
                        Double[] total = sections.get(section.getSection());
                        sections.put(section.getSection(), new Double[] { (total == null ? 0.0 : total[0].doubleValue()), request.getWeight() + (total == null ? 0.0 : total[1].doubleValue()) });
                    }
                }
            }
            if (iOverlapsAllEnrollments)
                availableValues = values;
            if (!availableValues.isEmpty() && iType.hasOverlaps()) {
                List<Map<CourseSection, List<CourseSection>>> conflicts = new ArrayList<Map<CourseSection, List<CourseSection>>>();
                for (Enrollment enrollment : availableValues) {
                    Map<CourseSection, List<CourseSection>> overlaps = new HashMap<CourseSection, List<CourseSection>>();
                    for (Request other : request.getStudent().getRequests()) {
                        Enrollment otherEnrollment = assignment.getValue(other);
                        if (other.equals(request) || otherEnrollment == null || other instanceof FreeTimeRequest)
                            continue;
                        if (enrollment.isOverlapping(otherEnrollment))
                            for (Section a : enrollment.getSections()) for (Section b : otherEnrollment.getSections()) if (a.getTime() != null && b.getTime() != null && !a.isAllowOverlap() && !b.isAllowOverlap() && !a.isToIgnoreStudentConflictsWith(b.getId()) && a.getTime().hasIntersection(b.getTime()) && !canIgnore(assignment, enrollment, a, availableValues)) {
                                List<CourseSection> x = overlaps.get(new CourseSection(enrollment.getCourse(), a));
                                if (x == null) {
                                    x = new ArrayList<CourseSection>();
                                    overlaps.put(new CourseSection(enrollment.getCourse(), a), x);
                                }
                                x.add(new CourseSection(otherEnrollment.getCourse(), b));
                            }
                    }
                    if (!overlaps.isEmpty()) {
                        conflicts.add(overlaps);
                        Set<Long> total = totals.get(enrollment.getCourse());
                        if (total == null) {
                            total = new HashSet<Long>();
                            totals.put(enrollment.getCourse(), total);
                        }
                        total.add(enrollment.getStudent().getId());
                    }
                }
                double fraction = request.getWeight() / conflicts.size();
                for (Map<CourseSection, List<CourseSection>> overlaps : conflicts) {
                    for (Map.Entry<CourseSection, List<CourseSection>> entry : overlaps.entrySet()) {
                        CourseSection a = entry.getKey();
                        Double total = sectionOverlaps.get(a);
                        sectionOverlaps.put(a, fraction + (total == null ? 0.0 : total.doubleValue()));
                        Map<CourseSection, Double> pair = conflictingPairs.get(a);
                        if (pair == null) {
                            pair = new HashMap<CourseSection, Double>();
                            conflictingPairs.put(a, pair);
                        }
                        for (CourseSection b : entry.getValue()) {
                            Double prev = pair.get(b);
                            pair.put(b, fraction + (prev == null ? 0.0 : prev.doubleValue()));
                        }
                    }
                }
            }
        }
    }
    Comparator<Course> courseComparator = new Comparator<Course>() {

        @Override
        public int compare(Course a, Course b) {
            int cmp = a.getName().compareTo(b.getName());
            if (cmp != 0)
                return cmp;
            return a.getId() < b.getId() ? -1 : a.getId() == b.getId() ? 0 : 1;
        }
    };
    Comparator<Section> sectionComparator = new Comparator<Section>() {

        @Override
        public int compare(Section a, Section b) {
            int cmp = a.getSubpart().getConfig().getOffering().getName().compareTo(b.getSubpart().getConfig().getOffering().getName());
            if (cmp != 0)
                return cmp;
            cmp = a.getSubpart().getInstructionalType().compareTo(b.getSubpart().getInstructionalType());
            // cmp = a.getName().compareTo(b.getName());
            if (cmp != 0)
                return cmp;
            return a.getId() < b.getId() ? -1 : a.getId() == b.getId() ? 0 : 1;
        }
    };
    CSVFile csv = new CSVFile();
    List<CSVFile.CSVField> headers = new ArrayList<CSVFile.CSVField>();
    headers.add(new CSVFile.CSVField("Course"));
    headers.add(new CSVFile.CSVField("Total\nConflicts"));
    if (iType.hasUnavailabilities()) {
        headers.add(new CSVFile.CSVField("Course\nEnrollment"));
        headers.add(new CSVFile.CSVField("Course\nLimit"));
    }
    headers.add(new CSVFile.CSVField("Class"));
    headers.add(new CSVFile.CSVField("Meeting Time"));
    if (iType.hasUnavailabilities()) {
        headers.add(new CSVFile.CSVField("Availability\nConflicts"));
        headers.add(new CSVFile.CSVField("% of Total\nConflicts"));
    }
    if (iType.hasOverlaps()) {
        headers.add(new CSVFile.CSVField("Time\nConflicts"));
        headers.add(new CSVFile.CSVField("% of Total\nConflicts"));
    }
    if (iType.hasUnavailabilities()) {
        headers.add(new CSVFile.CSVField("Class\nEnrollment"));
        headers.add(new CSVFile.CSVField("Class\nLimit"));
        if (!iType.hasOverlaps())
            headers.add(new CSVFile.CSVField("Class\nPotential"));
    }
    if (iType.hasOverlaps()) {
        headers.add(new CSVFile.CSVField("Conflicting\nClass"));
        headers.add(new CSVFile.CSVField("Conflicting\nMeeting Time"));
        headers.add(new CSVFile.CSVField("Joined\nConflicts"));
        headers.add(new CSVFile.CSVField("% of Total\nConflicts"));
    }
    csv.setHeader(headers);
    TreeSet<Course> courses = new TreeSet<Course>(courseComparator);
    courses.addAll(totals.keySet());
    for (Course course : courses) {
        Map<Section, Double[]> sectionUnavailability = unavailabilities.get(course);
        Set<Long> total = totals.get(course);
        TreeSet<Section> sections = new TreeSet<Section>(sectionComparator);
        if (sectionUnavailability != null)
            sections.addAll(sectionUnavailability.keySet());
        for (Map.Entry<CourseSection, Double> entry : sectionOverlaps.entrySet()) if (course.equals(entry.getKey().getCourse()))
            sections.add(entry.getKey().getSection());
        boolean firstCourse = true;
        for (Section section : sections) {
            Double[] sectionUnavailable = (sectionUnavailability == null ? null : sectionUnavailability.get(section));
            Double sectionOverlap = sectionOverlaps.get(new CourseSection(course, section));
            Map<CourseSection, Double> pair = conflictingPairs.get(new CourseSection(course, section));
            if (pair == null) {
                List<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>();
                line.add(new CSVFile.CSVField(firstCourse ? course.getName() : ""));
                line.add(new CSVFile.CSVField(firstCourse ? total.size() : ""));
                if (iType.hasUnavailabilities()) {
                    line.add(new CSVFile.CSVField(firstCourse ? sDF1.format(course.getEnrollmentWeight(assignment, null)) : ""));
                    line.add(new CSVFile.CSVField(firstCourse ? course.getLimit() < 0 ? "" : String.valueOf(course.getLimit()) : ""));
                }
                line.add(new CSVFile.CSVField(section.getSubpart().getName() + " " + section.getName(course.getId())));
                line.add(new CSVFile.CSVField(section.getTime() == null ? "" : section.getTime().getDayHeader() + " " + section.getTime().getStartTimeHeader(useAmPm) + " - " + section.getTime().getEndTimeHeader(useAmPm)));
                if (iType.hasUnavailabilities()) {
                    line.add(new CSVFile.CSVField(sectionUnavailable != null ? sDF2.format(sectionUnavailable[0]) : ""));
                    line.add(new CSVFile.CSVField(sectionUnavailable != null ? sDF2.format(sectionUnavailable[0] / total.size()) : ""));
                }
                if (iType.hasOverlaps()) {
                    line.add(new CSVFile.CSVField(sectionOverlap != null ? sDF2.format(sectionOverlap) : ""));
                    line.add(new CSVFile.CSVField(sectionOverlap != null ? sDF2.format(sectionOverlap / total.size()) : ""));
                }
                if (iType.hasUnavailabilities()) {
                    line.add(new CSVFile.CSVField(sDF1.format(section.getEnrollmentWeight(assignment, null))));
                    line.add(new CSVFile.CSVField(section.getLimit() < 0 ? "" : String.valueOf(section.getLimit())));
                    if (!iType.hasOverlaps())
                        line.add(new CSVFile.CSVField(sectionUnavailable != null ? sDF1.format(sectionUnavailable[1]) : ""));
                }
                csv.addLine(line);
            } else {
                boolean firstClass = true;
                for (CourseSection other : new TreeSet<CourseSection>(pair.keySet())) {
                    List<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>();
                    line.add(new CSVFile.CSVField(firstCourse && firstClass ? course.getName() : ""));
                    line.add(new CSVFile.CSVField(firstCourse && firstClass ? total.size() : ""));
                    if (iType.hasUnavailabilities()) {
                        line.add(new CSVFile.CSVField(firstCourse && firstClass ? sDF1.format(course.getEnrollmentWeight(assignment, null)) : ""));
                        line.add(new CSVFile.CSVField(firstCourse && firstClass ? course.getLimit() < 0 ? "" : String.valueOf(course.getLimit()) : ""));
                    }
                    line.add(new CSVFile.CSVField(firstClass ? section.getSubpart().getName() + " " + section.getName(course.getId()) : ""));
                    line.add(new CSVFile.CSVField(firstClass ? section.getTime() == null ? "" : section.getTime().getDayHeader() + " " + section.getTime().getStartTimeHeader(useAmPm) + " - " + section.getTime().getEndTimeHeader(useAmPm) : ""));
                    if (iType.hasUnavailabilities()) {
                        line.add(new CSVFile.CSVField(firstClass && sectionUnavailable != null ? sDF2.format(sectionUnavailable[0]) : ""));
                        line.add(new CSVFile.CSVField(sectionUnavailable != null ? sDF2.format(sectionUnavailable[0] / total.size()) : ""));
                    }
                    line.add(new CSVFile.CSVField(firstClass && sectionOverlap != null ? sDF2.format(sectionOverlap) : ""));
                    line.add(new CSVFile.CSVField(firstClass && sectionOverlap != null ? sDF2.format(sectionOverlap / total.size()) : ""));
                    if (iType.hasUnavailabilities()) {
                        line.add(new CSVFile.CSVField(firstClass ? sDF1.format(section.getEnrollmentWeight(assignment, null)) : ""));
                        line.add(new CSVFile.CSVField(firstClass ? section.getLimit() < 0 ? "" : String.valueOf(section.getLimit()) : ""));
                    }
                    line.add(new CSVFile.CSVField(other.getCourse().getName() + " " + other.getSection().getSubpart().getName() + " " + other.getSection().getName(other.getCourse().getId())));
                    line.add(new CSVFile.CSVField(other.getSection().getTime().getDayHeader() + " " + other.getSection().getTime().getStartTimeHeader(useAmPm) + " - " + other.getSection().getTime().getEndTimeHeader(useAmPm)));
                    line.add(new CSVFile.CSVField(sDF2.format(pair.get(other))));
                    line.add(new CSVFile.CSVField(sDF2.format(pair.get(other) / total.size())));
                    csv.addLine(line);
                    firstClass = false;
                }
            }
            firstCourse = false;
        }
        csv.addLine();
    }
    return csv;
}
Also used : Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) CSVFile(org.cpsolver.ifs.util.CSVFile) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) DataProperties(org.cpsolver.ifs.util.DataProperties) Comparator(java.util.Comparator) TreeSet(java.util.TreeSet) Enrollment(org.cpsolver.studentsct.model.Enrollment) ArrayList(java.util.ArrayList) List(java.util.List) Course(org.cpsolver.studentsct.model.Course) HashSet(java.util.HashSet) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) FreeTimeRequest(org.cpsolver.studentsct.model.FreeTimeRequest) Request(org.cpsolver.studentsct.model.Request) Section(org.cpsolver.studentsct.model.Section) GlobalConstraint(org.cpsolver.ifs.model.GlobalConstraint) CourseRequest(org.cpsolver.studentsct.model.CourseRequest) SectionLimit(org.cpsolver.studentsct.constraint.SectionLimit) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

GlobalConstraint (org.cpsolver.ifs.model.GlobalConstraint)4 ArrayList (java.util.ArrayList)3 Comparator (java.util.Comparator)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Map (java.util.Map)2 Lecture (org.cpsolver.coursett.model.Lecture)2 Placement (org.cpsolver.coursett.model.Placement)2 Constraint (org.cpsolver.ifs.model.Constraint)2 WeakeningConstraint (org.cpsolver.ifs.model.WeakeningConstraint)2 CSVFile (org.cpsolver.ifs.util.CSVFile)2 DataProperties (org.cpsolver.ifs.util.DataProperties)2 SectionLimit (org.cpsolver.studentsct.constraint.SectionLimit)2 Course (org.cpsolver.studentsct.model.Course)2 CourseRequest (org.cpsolver.studentsct.model.CourseRequest)2 Enrollment (org.cpsolver.studentsct.model.Enrollment)2 Request (org.cpsolver.studentsct.model.Request)2 List (java.util.List)1 Set (java.util.Set)1 TreeSet (java.util.TreeSet)1