use of org.cpsolver.studentsct.model.RequestGroup in project cpsolver by UniTime.
the class StudentSectioningXMLSaver method saveCourseRequest.
/**
* Save course request
* @param requestEl request element to be populated
* @param request course request to be saved
*/
protected void saveCourseRequest(Element requestEl, CourseRequest request) {
requestEl.addAttribute("id", getId("request", request.getId()));
requestEl.addAttribute("priority", String.valueOf(request.getPriority()));
if (request.isAlternative())
requestEl.addAttribute("alternative", "true");
if (request.getWeight() != 1.0)
requestEl.addAttribute("weight", sStudentWeightFormat.format(request.getWeight()));
requestEl.addAttribute("waitlist", request.isWaitlist() ? "true" : "false");
if (request.getTimeStamp() != null)
requestEl.addAttribute("timeStamp", request.getTimeStamp().toString());
boolean first = true;
for (Course course : request.getCourses()) {
if (first)
requestEl.addAttribute("course", getId("course", course.getId()));
else
requestEl.addElement("alternative").addAttribute("course", getId("course", course.getId()));
first = false;
}
for (Choice choice : request.getWaitlistedChoices()) {
Element choiceEl = requestEl.addElement("waitlisted");
choiceEl.addAttribute("offering", getId("offering", choice.getOffering().getId()));
choiceEl.setText(choice.getId());
}
for (Choice choice : request.getSelectedChoices()) {
Element choiceEl = requestEl.addElement("selected");
choiceEl.addAttribute("offering", getId("offering", choice.getOffering().getId()));
choiceEl.setText(choice.getId());
}
if (iSaveInitial && request.getInitialAssignment() != null) {
saveEnrollment(requestEl.addElement("initial"), request.getInitialAssignment());
}
if (iSaveCurrent && getAssignment().getValue(request) != null) {
saveEnrollment(requestEl.addElement("current"), getAssignment().getValue(request));
}
if (iSaveBest && request.getBestAssignment() != null) {
saveEnrollment(requestEl.addElement("best"), request.getBestAssignment());
}
for (RequestGroup g : request.getRequestGroups()) {
Element groupEl = requestEl.addElement("group").addAttribute("id", getId("group", g.getId())).addAttribute("course", getId("course", g.getCourse().getId()));
if (iShowNames)
groupEl.addAttribute("name", g.getName());
}
}
use of org.cpsolver.studentsct.model.RequestGroup in project cpsolver by UniTime.
the class StudentSectioningModel method getInfo.
/**
* Model info
*/
@Override
public Map<String, String> getInfo(Assignment<Request, Enrollment> assignment) {
Map<String, String> info = super.getInfo(assignment);
StudentSectioningModelContext context = getContext(assignment);
if (!getStudents().isEmpty())
info.put("Students with complete schedule", sDoubleFormat.format(100.0 * context.nrComplete() / getStudents().size()) + "% (" + context.nrComplete() + "/" + getStudents().size() + ")");
if (getDistanceConflict() != null && getDistanceConflict().getTotalNrConflicts(assignment) != 0)
info.put("Student distance conflicts", String.valueOf(getDistanceConflict().getTotalNrConflicts(assignment)));
if (getTimeOverlaps() != null && getTimeOverlaps().getTotalNrConflicts(assignment) != 0)
info.put("Time overlapping conflicts", String.valueOf(getTimeOverlaps().getTotalNrConflicts(assignment)));
int nrLastLikeStudents = getNrLastLikeStudents(false);
if (nrLastLikeStudents != 0 && nrLastLikeStudents != getStudents().size()) {
int nrRealStudents = getStudents().size() - nrLastLikeStudents;
int nrLastLikeCompleteStudents = getNrCompleteLastLikeStudents(assignment, false);
int nrRealCompleteStudents = context.nrComplete() - nrLastLikeCompleteStudents;
if (nrLastLikeStudents > 0)
info.put("Projected students with complete schedule", sDecimalFormat.format(100.0 * nrLastLikeCompleteStudents / nrLastLikeStudents) + "% (" + nrLastLikeCompleteStudents + "/" + nrLastLikeStudents + ")");
if (nrRealStudents > 0)
info.put("Real students with complete schedule", sDecimalFormat.format(100.0 * nrRealCompleteStudents / nrRealStudents) + "% (" + nrRealCompleteStudents + "/" + nrRealStudents + ")");
int nrLastLikeRequests = getNrLastLikeRequests(false);
int nrRealRequests = variables().size() - nrLastLikeRequests;
int nrLastLikeAssignedRequests = context.getNrAssignedLastLikeRequests();
int nrRealAssignedRequests = assignment.nrAssignedVariables() - nrLastLikeAssignedRequests;
if (nrLastLikeRequests > 0)
info.put("Projected assigned requests", sDecimalFormat.format(100.0 * nrLastLikeAssignedRequests / nrLastLikeRequests) + "% (" + nrLastLikeAssignedRequests + "/" + nrLastLikeRequests + ")");
if (nrRealRequests > 0)
info.put("Real assigned requests", sDecimalFormat.format(100.0 * nrRealAssignedRequests / nrRealRequests) + "% (" + nrRealAssignedRequests + "/" + nrRealRequests + ")");
if (getDistanceConflict() != null && getDistanceConflict().getTotalNrConflicts(assignment) > 0)
info.put("Student distance conflicts", String.valueOf(getDistanceConflict().getTotalNrConflicts(assignment)));
if (getTimeOverlaps() != null && getTimeOverlaps().getTotalNrConflicts(assignment) > 0)
info.put("Time overlapping conflicts", String.valueOf(getTimeOverlaps().getTotalNrConflicts(assignment)));
}
context.getInfo(assignment, info);
double groupSpread = 0.0;
double groupCount = 0;
for (Offering offering : iOfferings) {
for (Course course : offering.getCourses()) {
for (RequestGroup group : course.getRequestGroups()) {
groupSpread += group.getAverageSpread(assignment) * group.getEnrollmentWeight(assignment, null);
groupCount += group.getEnrollmentWeight(assignment, null);
}
}
}
if (groupCount > 0)
info.put("Same group", sDecimalFormat.format(100.0 * groupSpread / groupCount) + "%");
return info;
}
use of org.cpsolver.studentsct.model.RequestGroup in project cpsolver by UniTime.
the class StudentSectioningModel method toString.
@Override
public String toString(Assignment<Request, Enrollment> assignment) {
double groupSpread = 0.0;
double groupCount = 0;
for (Offering offering : iOfferings) {
for (Course course : offering.getCourses()) {
for (RequestGroup group : course.getRequestGroups()) {
groupSpread += group.getAverageSpread(assignment) * group.getEnrollmentWeight(assignment, null);
groupCount += group.getEnrollmentWeight(assignment, null);
}
}
}
return (getNrRealStudents(false) > 0 ? "RRq:" + getNrAssignedRealRequests(assignment, false) + "/" + getNrRealRequests(false) + ", " : "") + (getNrLastLikeStudents(false) > 0 ? "DRq:" + getNrAssignedLastLikeRequests(assignment, false) + "/" + getNrLastLikeRequests(false) + ", " : "") + (getNrRealStudents(false) > 0 ? "RS:" + getNrCompleteRealStudents(assignment, false) + "/" + getNrRealStudents(false) + ", " : "") + (getNrLastLikeStudents(false) > 0 ? "DS:" + getNrCompleteLastLikeStudents(assignment, false) + "/" + getNrLastLikeStudents(false) + ", " : "") + "V:" + sDecimalFormat.format(-getTotalValue(assignment)) + (getDistanceConflict() == null ? "" : ", DC:" + getDistanceConflict().getTotalNrConflicts(assignment)) + (getTimeOverlaps() == null ? "" : ", TOC:" + getTimeOverlaps().getTotalNrConflicts(assignment)) + (iMPP ? ", IS:" + sDecimalFormat.format(100.0 * getContext(assignment).iAssignedSameSectionWeight / iTotalMPPCRWeight) + "%" : "") + (iMPP ? ", IT:" + sDecimalFormat.format(100.0 * getContext(assignment).iAssignedSameTimeWeight / iTotalMPPCRWeight) + "%" : "") + ", %:" + sDecimalFormat.format(-100.0 * getTotalValue(assignment) / (getStudents().size() - iNrDummyStudents + (iProjectedStudentWeight < 0.0 ? iNrDummyStudents * (iTotalDummyWeight / iNrDummyRequests) : iProjectedStudentWeight * iTotalDummyWeight))) + (groupCount > 0 ? ", SG:" + sDecimalFormat.format(100.0 * groupSpread / groupCount) + "%" : "");
}
use of org.cpsolver.studentsct.model.RequestGroup in project cpsolver by UniTime.
the class RequestGroupTable method create.
@Override
public CSVFile create(Assignment<Request, Enrollment> assignment, DataProperties properties) {
boolean useAmPm = properties.getPropertyBoolean("useAmPm", true);
CSVFile csv = new CSVFile();
csv.setHeader(new CSVFile.CSVField[] { new CSVFile.CSVField("Group"), new CSVFile.CSVField("Course"), new CSVFile.CSVField("Total\nSpread"), new CSVFile.CSVField("Group\nEnrollment"), new CSVFile.CSVField("Class"), new CSVFile.CSVField("Meeting Time"), new CSVFile.CSVField("Class\nSpread"), new CSVFile.CSVField("Class\nEnrollment"), new CSVFile.CSVField("Class\nLimit") });
TreeSet<RequestGroup> groups = new TreeSet<RequestGroup>(new Comparator<RequestGroup>() {
@Override
public int compare(RequestGroup g1, RequestGroup g2) {
int cmp = g1.getName().compareTo(g2.getName());
if (cmp != 0)
return cmp;
cmp = g1.getCourse().getName().compareTo(g2.getCourse().getName());
if (cmp != 0)
return cmp;
if (g1.getId() < g2.getId())
return -1;
if (g1.getId() > g2.getId())
return 1;
return (g1.getCourse().getId() < g2.getCourse().getId() ? -1 : g1.getCourse().getId() > g2.getCourse().getId() ? 1 : 0);
}
});
for (Offering offering : iModel.getOfferings()) for (Course course : offering.getCourses()) groups.addAll(course.getRequestGroups());
for (RequestGroup group : groups) {
double groupEnrollment = group.getEnrollmentWeight(assignment, null);
double groupSpread = group.getAverageSpread(assignment);
for (Config config : group.getCourse().getOffering().getConfigs()) for (Subpart subpart : config.getSubparts()) for (Section section : subpart.getSections()) {
double s = group.getSectionWeight(assignment, section, null);
if (s > 0.00001) {
csv.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(group.getName()), new CSVFile.CSVField(group.getCourse().getName()), new CSVFile.CSVField(sDF.format(100.0 * groupSpread)), new CSVFile.CSVField(Math.round(groupEnrollment)), new CSVFile.CSVField(section.getSubpart().getName() + " " + section.getName(group.getCourse().getId())), new CSVFile.CSVField(section.getTime() == null ? "" : section.getTime().getDayHeader() + " " + section.getTime().getStartTimeHeader(useAmPm) + " - " + section.getTime().getEndTimeHeader(useAmPm)), new CSVFile.CSVField(sDF.format(100.0 * group.getSectionSpread(assignment, section))), new CSVFile.CSVField(Math.round(group.getSectionWeight(assignment, section, null))), new CSVFile.CSVField(section.getLimit()) });
}
}
}
return csv;
}
use of org.cpsolver.studentsct.model.RequestGroup 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());
}
Aggregations