use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class CourseLimitCheck method check.
/**
* Check for courses where the limit is below the number of students that
* request the course
*
* @return false, if there is such a case
*/
public boolean check() {
sLog.info("Checking for course limits...");
boolean ret = true;
for (Offering offering : getModel().getOfferings()) {
boolean hasUnlimitedSection = false;
if (iFixUnlimited)
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
if (section.getLimit() < 0)
hasUnlimitedSection = true;
}
}
}
int offeringLimit = 0;
int nrStudents = 0;
for (Course course : offering.getCourses()) {
if (course.getLimit() < 0) {
offeringLimit = -1;
continue;
}
if (iFixUnlimited && hasUnlimitedSection) {
sLog.info("Course " + course + " made unlimited.");
course.setLimit(-1);
offeringLimit = -1;
continue;
}
double total = 0;
double lastLike = 0, real = 0;
for (Request request : getModel().variables()) {
if (request instanceof CourseRequest && ((CourseRequest) request).getCourses().contains(course)) {
total += request.getWeight();
if (request.getStudent().isDummy())
lastLike += request.getWeight();
else
real += request.getWeight();
}
}
nrStudents += Math.round(total);
offeringLimit += course.getLimit();
if (Math.round(total) > course.getLimit()) {
sLog.error("Course " + course + " is requested by " + sDF.format(total) + " students, but its limit is only " + course.getLimit());
ret = false;
iCSVFile.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(course.getName()), new CSVFile.CSVField(course.getLimit()), new CSVFile.CSVField(total), new CSVFile.CSVField(real), new CSVFile.CSVField(lastLike) });
if (iUpZeroLimits && course.getLimit() == 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
} else if (iUpNonZeroLimits && course.getLimit() > 0) {
int oldLimit = course.getLimit();
course.setLimit((int) Math.round(total));
sLog.info(" -- limit of course " + course + " increased to " + course.getLimit() + " (was " + oldLimit + ")");
}
}
}
if (iUpZeroLimits && offeringLimit == 0 && nrStudents > 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(nrStudents / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && offeringLimit >= 0 && nrStudents > offeringLimit) {
double fact = ((double) nrStudents) / offeringLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
if (offeringLimit >= 0) {
int totalSectionLimit = 0;
for (Config config : offering.getConfigs()) {
int configLimit = -1;
for (Subpart subpart : config.getSubparts()) {
int subpartLimit = 0;
for (Section section : subpart.getSections()) {
subpartLimit += section.getLimit();
}
if (configLimit < 0)
configLimit = subpartLimit;
else
configLimit = Math.min(configLimit, subpartLimit);
}
totalSectionLimit += configLimit;
}
if (totalSectionLimit < offeringLimit) {
sLog.error("Offering limit of " + offering + " is " + offeringLimit + ", but total section limit is only " + totalSectionLimit);
if (iUpZeroLimits && totalSectionLimit == 0) {
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit(Math.max(section.getLimit(), (int) Math.ceil(((double) offeringLimit) / subpart.getSections().size())));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
} else if (iUpNonZeroLimits && totalSectionLimit > 0) {
double fact = ((double) offeringLimit) / totalSectionLimit;
for (Config config : offering.getConfigs()) {
for (Subpart subpart : config.getSubparts()) {
for (Section section : subpart.getSections()) {
int oldLimit = section.getLimit();
section.setLimit((int) Math.ceil(fact * section.getLimit()));
sLog.info(" -- limit of section " + section + " increased to " + section.getLimit() + " (was " + oldLimit + ")");
}
}
}
}
}
}
}
return ret;
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class StudentPreferencePenalties method setPenalties.
/**
* Set the computed penalties to all sections of all requests of the given
* student
* @param student given student
* @param distributionType penalty distribution type
*/
public static void setPenalties(Student student, int distributionType) {
if (sDebug)
sLog.debug("Setting penalties for " + student);
StudentPreferencePenalties penalties = new StudentPreferencePenalties(distributionType);
for (Request request : student.getRequests()) {
if (!(request instanceof CourseRequest))
continue;
CourseRequest courseRequest = (CourseRequest) request;
if (sDebug)
sLog.debug("-- " + courseRequest);
for (Course course : courseRequest.getCourses()) {
if (sDebug)
sLog.debug(" -- " + course.getName());
for (Config config : course.getOffering().getConfigs()) {
if (sDebug)
sLog.debug(" -- " + config.getName());
for (Subpart subpart : config.getSubparts()) {
if (sDebug)
sLog.debug(" -- " + subpart.getName());
for (Section section : subpart.getSections()) {
section.setPenalty(penalties.getPenalty(section));
if (sDebug)
sLog.debug(" -- " + section);
}
}
}
}
courseRequest.clearCache();
}
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class StudentSctBBTest method getMessages.
/**
* Return a list of messages ({@link Message} objects) from the sectioning
* of the given student
* @return enrollment messages
*/
public List<Message> getMessages() {
Assignment<Request, Enrollment> assignment = getSolution().getAssignment();
List<Message> ret = new ArrayList<Message>();
ret.add(new Message(Message.sMsgLevelInfo, null, "<li>Solution found in " + iTime + " ms."));
if (iTimeoutReached)
ret.add(new Message(Message.sMsgLevelInfo, null, "<li>Time out reached, solution optimality can not be guaranteed."));
for (Request request : getStudent().getRequests()) {
if (!request.isAlternative() && assignment.getValue(request) == null) {
ret.add(new Message(Message.sMsgLevelWarn, request, "<li>Unable to enroll to " + request + ", " + (request instanceof CourseRequest ? ((CourseRequest) request).getCourses().size() == 1 ? "course is" : "courses are" : "time is") + " not available."));
Collection<Enrollment> values = (request instanceof CourseRequest ? (Collection<Enrollment>) ((CourseRequest) request).getAvaiableEnrollmentsSkipSameTime(assignment) : request.computeEnrollments(assignment));
for (Iterator<Enrollment> f = values.iterator(); f.hasNext(); ) {
Enrollment enrollment = f.next();
Set<Enrollment> conf = conflictValues(assignment, enrollment);
if (conf != null && !conf.isEmpty()) {
Enrollment conflict = conf.iterator().next();
if (conflict.equals(enrollment))
ret.add(new Message(Message.sMsgLevelInfo, request, "<ul>Assignment of " + enrollment.getName().replaceAll("\n", "<br> ") + "<br> is not available."));
else
ret.add(new Message(Message.sMsgLevelInfo, request, "<ul>Assignment of " + enrollment.getName().replaceAll("\n", "<br> ") + "<br> conflicts with " + conflict.getName().replaceAll("\n", "<br> ") + "</ul>"));
}
}
}
if (request instanceof CourseRequest && assignment.getValue(request) != null) {
CourseRequest courseRequest = (CourseRequest) request;
Enrollment enrollment = assignment.getValue(request);
List<Enrollment> selectedEnrollments = courseRequest.getSelectedEnrollments(assignment, false);
if (selectedEnrollments != null && !selectedEnrollments.isEmpty() && !selectedEnrollments.contains(enrollment)) {
Course course = (courseRequest.getSelectedChoices().iterator().next()).getOffering().getCourse(getStudent());
Enrollment selected = selectedEnrollments.get(0);
Set<Enrollment> conf = conflictValues(assignment, selected);
if (conf != null && !conf.isEmpty()) {
ret.add(new Message(Message.sMsgLevelWarn, request, "<li>Unable to enroll selected enrollment for " + course.getName() + ", seleted " + (courseRequest.getSelectedChoices().size() == 1 ? "class is" : "classes are") + " conflicting with other choices."));
Enrollment conflict = conf.iterator().next();
if (conflict.equals(selected))
ret.add(new Message(Message.sMsgLevelInfo, request, "<ul>Assignment of " + selected.getName().replaceAll("\n", "<br> ") + "<br> is not available."));
else
ret.add(new Message(Message.sMsgLevelInfo, request, "<ul>Assignment of " + selected.getName().replaceAll("\n", "<br> ") + "<br> conflicts with " + conflict.getName().replaceAll("\n", "<br> ") + "</ul>"));
} else {
ret.add(new Message(Message.sMsgLevelWarn, request, "<li>Unable to enroll selected enrollment for " + course.getName() + "."));
}
}
}
}
return ret;
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class Test method updateSpace.
public static void updateSpace(Assignment<Request, Enrollment> assignment, Enrollment enrollment, boolean increment) {
if (enrollment == null || !enrollment.isCourseRequest())
return;
for (Section section : enrollment.getSections()) section.setSpaceHeld(section.getSpaceHeld() + (increment ? 1.0 : -1.0));
List<Enrollment> feasibleEnrollments = new ArrayList<Enrollment>();
int totalLimit = 0;
for (Enrollment enrl : enrollment.getRequest().values(assignment)) {
if (!enrl.getCourse().equals(enrollment.getCourse()))
continue;
boolean overlaps = false;
for (Request otherRequest : enrollment.getRequest().getStudent().getRequests()) {
if (otherRequest.equals(enrollment.getRequest()) || !(otherRequest instanceof CourseRequest))
continue;
Enrollment otherErollment = assignment.getValue(otherRequest);
if (otherErollment == null)
continue;
if (enrl.isOverlapping(otherErollment)) {
overlaps = true;
break;
}
}
if (!overlaps) {
feasibleEnrollments.add(enrl);
if (totalLimit >= 0) {
int limit = enrl.getLimit();
if (limit < 0)
totalLimit = -1;
else
totalLimit += limit;
}
}
}
double change = enrollment.getRequest().getWeight() / (totalLimit > 0 ? totalLimit : feasibleEnrollments.size());
for (Enrollment feasibleEnrollment : feasibleEnrollments) for (Section section : feasibleEnrollment.getSections()) {
if (totalLimit > 0) {
section.setSpaceExpected(section.getSpaceExpected() + (increment ? +change : -change) * feasibleEnrollment.getLimit());
} else {
section.setSpaceExpected(section.getSpaceExpected() + (increment ? +change : -change));
}
}
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class LinkedSections method createConstraint.
/**
* Create linked-section constraints for a given student
*/
private LinkedSectionsConstraint createConstraint(Student student) {
List<Request> requests = new ArrayList<Request>();
int nrOfferings = 0;
requests: for (Request request : student.getRequests()) {
if (request instanceof CourseRequest) {
for (Course course : ((CourseRequest) request).getCourses()) {
Map<Subpart, Set<Section>> subpartsThisOffering = iSections.get(course.getOffering());
if (subpartsThisOffering != null) {
requests.add(request);
nrOfferings++;
continue requests;
}
}
}
}
if (nrOfferings <= 1)
return null;
LinkedSectionsConstraint constraint = new LinkedSectionsConstraint(student, requests);
student.getRequests().get(0).getModel().addConstraint(constraint);
return constraint;
}
Aggregations