use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class RandomizedBacktrackNeighbourSelection method values.
/**
* List of values of a variable.
* {@link CourseRequest#computeRandomEnrollments(Assignment, int)} with the provided
* limit is used for a {@link CourseRequest}.
*/
@Override
protected Iterator<Enrollment> values(BacktrackNeighbourSelection<Request, Enrollment>.BacktrackNeighbourSelectionContext<Request, Enrollment> context, Request variable) {
if (variable instanceof CourseRequest) {
final CourseRequest request = (CourseRequest) variable;
final StudentSectioningModel model = (StudentSectioningModel) context.getModel();
final Assignment<Request, Enrollment> assignment = context.getAssignment();
List<Enrollment> values = (iMaxValues > 0 ? request.computeRandomEnrollments(assignment, iMaxValues) : request.computeEnrollments(assignment));
Collections.sort(values, new Comparator<Enrollment>() {
private HashMap<Enrollment, Double> iValues = new HashMap<Enrollment, Double>();
private Double value(Enrollment e) {
Double value = iValues.get(e);
if (value == null) {
value = model.getStudentWeights().getWeight(assignment, e, (model.getDistanceConflict() == null ? null : model.getDistanceConflict().conflicts(e)), (model.getTimeOverlaps() == null ? null : model.getTimeOverlaps().conflicts(e)));
iValues.put(e, value);
}
return value;
}
@Override
public int compare(Enrollment e1, Enrollment e2) {
if (e1.equals(assignment.getValue(request)))
return -1;
if (e2.equals(assignment.getValue(request)))
return 1;
Double v1 = value(e1), v2 = value(e2);
return v1.equals(v2) ? e1.compareTo(assignment, e2) : v2.compareTo(v1);
}
});
return values.iterator();
} else {
return variable.computeEnrollments(context.getAssignment()).iterator();
}
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class Test method getMinMaxEnrollmentPenalty.
/**
* Minimum and maximum enrollment penalty, i.e.,
* {@link Enrollment#getPenalty()} of all enrollments
* @param request a course request
* @return minimum and maximum of the enrollment penalty
*/
public static double[] getMinMaxEnrollmentPenalty(CourseRequest request) {
List<Enrollment> enrollments = request.values(new EmptyAssignment<Request, Enrollment>());
if (enrollments.isEmpty())
return new double[] { 0, 0 };
double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
for (Enrollment enrollment : enrollments) {
double penalty = enrollment.getPenalty();
min = Math.min(min, penalty);
max = Math.max(max, penalty);
}
return new double[] { min, max };
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class Test method loadLastLikeCourseDemandsXml.
/**
* Load last-like students from an XML file (the one that is used to load
* last like course demands table in the timetabling application)
* @param model problem model
* @param xml an XML file
*/
public static void loadLastLikeCourseDemandsXml(StudentSectioningModel model, File xml) {
try {
Document document = (new SAXReader()).read(xml);
Element root = document.getRootElement();
HashMap<Course, List<Request>> requests = new HashMap<Course, List<Request>>();
long reqId = 0;
for (Iterator<?> i = root.elementIterator("student"); i.hasNext(); ) {
Element studentEl = (Element) i.next();
Student student = new Student(Long.parseLong(studentEl.attributeValue("externalId")));
student.setDummy(true);
int priority = 0;
HashSet<Course> reqCourses = new HashSet<Course>();
for (Iterator<?> j = studentEl.elementIterator("studentCourse"); j.hasNext(); ) {
Element courseEl = (Element) j.next();
String subjectArea = courseEl.attributeValue("subject");
String courseNbr = courseEl.attributeValue("courseNumber");
Course course = null;
offerings: for (Offering offering : model.getOfferings()) {
for (Course c : offering.getCourses()) {
if (c.getSubjectArea().equals(subjectArea) && c.getCourseNumber().equals(courseNbr)) {
course = c;
break offerings;
}
}
}
if (course == null && courseNbr.charAt(courseNbr.length() - 1) >= 'A' && courseNbr.charAt(courseNbr.length() - 1) <= 'Z') {
String courseNbrNoSfx = courseNbr.substring(0, courseNbr.length() - 1);
offerings: for (Offering offering : model.getOfferings()) {
for (Course c : offering.getCourses()) {
if (c.getSubjectArea().equals(subjectArea) && c.getCourseNumber().equals(courseNbrNoSfx)) {
course = c;
break offerings;
}
}
}
}
if (course == null) {
sLog.warn("Course " + subjectArea + " " + courseNbr + " not found.");
} else {
if (!reqCourses.add(course)) {
sLog.warn("Course " + subjectArea + " " + courseNbr + " already requested.");
} else {
List<Course> courses = new ArrayList<Course>(1);
courses.add(course);
CourseRequest request = new CourseRequest(reqId++, priority++, false, student, courses, false, null);
List<Request> requestsThisCourse = requests.get(course);
if (requestsThisCourse == null) {
requestsThisCourse = new ArrayList<Request>();
requests.put(course, requestsThisCourse);
}
requestsThisCourse.add(request);
}
}
}
if (!student.getRequests().isEmpty())
model.addStudent(student);
}
for (Map.Entry<Course, List<Request>> entry : requests.entrySet()) {
Course course = entry.getKey();
List<Request> requestsThisCourse = entry.getValue();
double weight = getLastLikeStudentWeight(course, 0, requestsThisCourse.size());
for (Request request : requestsThisCourse) {
request.setWeight(weight);
}
}
} catch (Exception e) {
sLog.error(e.getMessage(), e);
}
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class InevitableStudentConflicts method check.
/**
* Check model for inevitable student conflicts
* @param assignment current assignment
* @return true if there are no inevitable student conflicts
*/
public boolean check(Assignment<Request, Enrollment> assignment) {
sLog.info("Checking for inevitable student conflicts...");
HashMap<TreeSet<Object>, Object[]> noGoods = new HashMap<TreeSet<Object>, Object[]>();
long studentWithoutCompleteSchedule = 0;
long inevitableRequests = 0;
double inevitableRequestWeight = 0.0;
long incompleteInevitableRequests = 0;
double incompleteInevitableRequestWeight = 0.0;
long total = 0;
Comparator<Object> simpleCmp = new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return o1.toString().compareTo(o2.toString());
}
};
HashSet<Request> requests2remove = new HashSet<Request>();
for (Student student : getModel().getStudents()) {
sLog.debug(" Checking " + (++total) + ". student " + student + "...");
if (student.isComplete(assignment)) {
for (Request request : student.getRequests()) {
if (assignment.getValue(request) == null) {
inevitableRequests++;
inevitableRequestWeight += request.getWeight();
}
}
} else {
StudentCheck ch = new StudentCheck(student.getRequests());
ch.check(assignment);
if (!ch.isBestComplete()) {
sLog.info(" Student " + student + " cannot have a complete schedule");
studentWithoutCompleteSchedule++;
}
int idx = 0;
for (Iterator<Request> f = student.getRequests().iterator(); f.hasNext(); idx++) {
Request request = f.next();
Enrollment enrollment = ch.getBestAssignment()[idx];
if (enrollment == null) {
if (!ch.isBestComplete()) {
List<Request> noGood = noGood(assignment, student, ch, idx);
sLog.info(" Request " + request + " cannot be assigned");
for (Request r : noGood) {
sLog.debug(" " + r);
Collection<Enrollment> values = null;
if (r instanceof CourseRequest) {
values = ((CourseRequest) r).getEnrollmentsSkipSameTime(assignment);
} else {
values = request.computeEnrollments(assignment);
}
for (Enrollment en : values) {
sLog.debug(" " + enrollment2string(en));
}
}
if (iDeleteInevitable) {
// noGood.lastElement()
requests2remove.add(request);
sLog.info(" -- request " + request + " picked to be removed from the model");
}
TreeSet<Object> key = new TreeSet<Object>(simpleCmp);
for (Request r : noGood) {
if (r instanceof CourseRequest) {
key.add(((CourseRequest) r).getCourses().get(0));
} else {
key.add("Free " + ((FreeTimeRequest) r).getTime().getLongName(true));
}
}
Object[] counter = noGoods.get(key);
int ir = (counter == null ? 1 : ((Integer) counter[0]).intValue() + 1);
double irw = (counter == null ? 0.0 : ((Double) counter[1]).doubleValue()) + request.getWeight();
noGoods.put(key, new Object[] { Integer.valueOf(ir), Double.valueOf(irw) });
if (ch.canAssign(request, idx)) {
incompleteInevitableRequests++;
incompleteInevitableRequestWeight += request.getWeight();
}
}
inevitableRequests++;
inevitableRequestWeight += request.getWeight();
}
}
}
}
for (Map.Entry<TreeSet<Object>, Object[]> entry : noGoods.entrySet()) {
TreeSet<Object> noGood = entry.getKey();
Object[] counter = entry.getValue();
List<CSVFile.CSVField> fields = new ArrayList<CSVFile.CSVField>();
String courseStr = "";
for (Iterator<Object> j = noGood.iterator(); j.hasNext(); ) {
Object x = j.next();
if (x instanceof Course) {
Course course = (Course) x;
courseStr += course.getName();
} else
courseStr += x.toString();
if (j.hasNext())
courseStr += ", ";
}
fields.add(new CSVFile.CSVField(courseStr));
fields.add(new CSVFile.CSVField(((Integer) counter[0]).intValue()));
fields.add(new CSVFile.CSVField(((Double) counter[1]).doubleValue()));
for (Iterator<Object> j = noGood.iterator(); j.hasNext(); ) {
Object x = j.next();
if (x instanceof Course) {
Course course = (Course) x;
List<Course> courses = new ArrayList<Course>(1);
courses.add(course);
CourseRequest cr = new CourseRequest(-1, 0, false, new Student(-1), courses, false, null);
String field = course.getName();
int idx = 0;
for (Iterator<Enrollment> k = cr.getEnrollmentsSkipSameTime(assignment).iterator(); k.hasNext(); ) {
if (idx++ > 20) {
field += "\n ...";
break;
} else {
field += "\n " + enrollment2string(k.next());
}
}
fields.add(new CSVFile.CSVField(field));
} else
fields.add(new CSVFile.CSVField(x.toString()));
}
iCSVFile.addLine(fields);
}
if (!requests2remove.isEmpty()) {
for (Request request : requests2remove) {
removeRequest(request);
}
}
sLog.info("Students that can never obtain a complete schedule: " + studentWithoutCompleteSchedule);
sLog.info("Inevitable student requests: " + inevitableRequests);
sLog.info("Inevitable student request weight: " + inevitableRequestWeight);
sLog.info("Inevitable student requests of students without a complete schedule: " + incompleteInevitableRequests);
sLog.info("Inevitable student request weight of students without a complete schedule: " + incompleteInevitableRequestWeight);
if (iCSVFile.getLines() != null)
Collections.sort(iCSVFile.getLines(), new Comparator<CSVFile.CSVLine>() {
@Override
public int compare(CSVFile.CSVLine l1, CSVFile.CSVLine l2) {
int cmp = Double.compare(l2.getField(1).toDouble(), l1.getField(1).toDouble());
if (cmp != 0)
return cmp;
return l1.getField(0).toString().compareTo(l2.getField(0).toString());
}
});
return (inevitableRequests == 0);
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class StudentPreferencePenalties method getMinMaxEnrollmentPenalty.
/**
* Minimal and maximal available enrollment penalty of a request
* @param request student course request
* @return minimal and maximal penalty
*/
public double[] getMinMaxEnrollmentPenalty(CourseRequest request) {
List<Enrollment> enrollments = request.values(new EmptyAssignment<Request, Enrollment>());
if (enrollments.isEmpty())
return new double[] { 0, 0 };
double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
for (Enrollment enrollment : enrollments) {
double penalty = getPenalty(enrollment);
min = Math.min(min, penalty);
max = Math.max(max, penalty);
}
return new double[] { min, max };
}
Aggregations