use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class BacktrackSelection method selectNeighbour.
@Override
public Neighbour<Request, Enrollment> selectNeighbour(Solution<Request, Enrollment> solution) {
Request request = null;
if (iNbrIterations > iMaxIterations)
return null;
while ((request = nextRequest()) != null) {
Progress.getInstance(solution.getModel()).incProgress();
Enrollment e = request.getAssignment(solution.getAssignment());
if (e != null && request instanceof FreeTimeRequest)
continue;
if (e != null && e.getPriority() == 0 && ((CourseRequest) request).getSelectedChoices().isEmpty())
continue;
for (int i = 0; i < 5; i++) {
try {
Neighbour<Request, Enrollment> n = iRBtNSel.selectNeighbour(solution, request);
if (iRBtNSel.getContext() != null) {
iNbrIterations++;
iTotalTime += iRBtNSel.getContext().getTime();
if (iRBtNSel.getContext().isTimeoutReached())
iNbrTimeoutReached++;
if (n == null)
iNbrNoSolution++;
}
if (n != null && n.value(solution.getAssignment()) <= 0.0)
return n;
break;
} catch (ConcurrentModificationException ex) {
}
}
}
return null;
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class StudentSchedulingAssistantWeights method getWeight.
@Override
public double getWeight(Assignment<Request, Enrollment> assignment, Enrollment enrollment) {
if (!enrollment.isCourseRequest())
return getBaseWeight(assignment, enrollment);
if (enrollment.getAssignments().isEmpty())
return 0;
double base = getBaseWeight(assignment, enrollment);
double weight = base;
int size = enrollment.getAssignments().size();
CourseRequest cr = (CourseRequest) enrollment.getRequest();
double[] best = best(assignment, cr);
double hasTime = 0;
double oexp = 0;
double penalty = 0.0;
for (Section section : enrollment.getSections()) {
if (section.getTime() != null)
hasTime++;
oexp += getOverExpected(assignment, section, cr);
penalty += section.getPenalty();
}
double noTime = best[0] - (hasTime / size);
double overExpected = oexp - best[1];
double avgPenalty = (penalty / size) - best[2];
double nrSelected = 0;
if (!cr.getSelectedChoices().isEmpty()) {
for (Section section : enrollment.getSections()) if (cr.isSelected(section))
nrSelected++;
}
double unselectedFraction = best[3] - (nrSelected / size);
double unavailableSize = 0;
double altSectionsWithLimit = 0;
for (Section section : enrollment.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)
unavailableSize += (averageSize - section.getLimit()) / averageSize;
altSectionsWithLimit++;
}
double unavailableSizeFraction = (unavailableSize > 0 ? unavailableSize / altSectionsWithLimit : 0.0);
weight -= overExpected * base * iOverExpectedFactor;
weight -= unselectedFraction * base * iSelectionFactor;
weight -= noTime * base * iNoTimeFactor;
weight -= unavailableSizeFraction * base * iAvailabilityFactor;
weight -= avgPenalty * iPenaltyFactor;
return round(weight);
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class SuggestionsBranchAndBound method values.
/**
* Domain of a request
* @param request given request
* @return possible enrollments (meeting the filter etc)
*/
protected List<Enrollment> values(final Request request) {
if (!request.equals(iSelectedRequest) && !request.getStudent().canAssign(iAssignment, request)) {
if (canLeaveUnassigned(request)) {
List<Enrollment> values = new ArrayList<Enrollment>();
Config config = null;
if (request instanceof CourseRequest)
config = ((CourseRequest) request).getCourses().get(0).getOffering().getConfigs().get(0);
values.add(new Enrollment(request, 0, config, new HashSet<Section>(), iAssignment));
return values;
}
return new ArrayList<Enrollment>();
}
List<Enrollment> values = iValues.get(request);
if (values != null)
return values;
if (request instanceof CourseRequest) {
CourseRequest cr = (CourseRequest) request;
values = (cr.equals(iSelectedRequest) ? cr.getAvaiableEnrollments(iAssignment) : cr.getAvaiableEnrollmentsSkipSameTime(iAssignment));
if (cr.equals(iSelectedRequest)) {
Collections.sort(values, new Comparator<Enrollment>() {
@Override
public int compare(Enrollment e1, Enrollment e2) {
int s1 = 0;
for (Section s : e1.getSections()) if (((CourseRequest) iSelectedRequest).isSelected(s))
s1++;
int s2 = 0;
for (Section s : e2.getSections()) if (((CourseRequest) iSelectedRequest).isSelected(s))
s2++;
if (s1 != s2)
return (s1 > s2 ? -1 : 1);
if (e1.getRequest().getInitialAssignment() != null) {
Enrollment original = e1.getRequest().getInitialAssignment();
int x1 = 0;
if (original.getCourse().equals(e1.getCourse()))
x1 += 100;
if (original.getConfig().equals(e1.getConfig())) {
x1 += 10;
for (Section section : original.getSections()) {
for (Section s : e1.getSections()) {
if (s.getSubpart().getId() == section.getSubpart().getId()) {
if (ToolBox.equals(section.getTime(), s.getTime()) && ToolBox.equals(section.getRooms(), s.getRooms()))
x1++;
break;
}
}
}
}
int x2 = 0;
if (original.getCourse().equals(e2.getCourse()))
x2 += 100;
if (original.getConfig().equals(e2.getConfig())) {
x2 += 10;
for (Section section : original.getSections()) {
for (Section s : e2.getSections()) {
if (s.getSubpart().getId() == section.getSubpart().getId()) {
if (ToolBox.equals(section.getTime(), s.getTime()) && ToolBox.equals(section.getRooms(), s.getRooms()))
x2++;
break;
}
}
}
}
if (x1 != x2) {
return (x1 > x2 ? -1 : 1);
}
}
return iComparator.compare(iAssignment, e1, e2);
}
});
} else {
Collections.sort(values, new Comparator<Enrollment>() {
@Override
public int compare(Enrollment e1, Enrollment e2) {
return iComparator.compare(iAssignment, e1, e2);
}
});
}
} else {
values = new ArrayList<Enrollment>();
values.add(((FreeTimeRequest) request).createEnrollment());
}
if (canLeaveUnassigned(request)) {
Config config = null;
if (request instanceof CourseRequest)
config = ((CourseRequest) request).getCourses().get(0).getOffering().getConfigs().get(0);
values.add(new Enrollment(request, 0, config, new HashSet<Section>(), iAssignment));
}
iValues.put(request, values);
if (request.equals(iSelectedRequest) && iFilter != null && request instanceof CourseRequest) {
for (Iterator<Enrollment> i = values.iterator(); i.hasNext(); ) {
Enrollment enrollment = i.next();
if (enrollment.getAssignments() != null && !enrollment.getAssignments().isEmpty()) {
boolean match = false;
for (Iterator<Section> j = enrollment.getSections().iterator(); j.hasNext(); ) {
Section section = j.next();
if (iSelectedSection != null) {
if (section.getSubpart().getId() == iSelectedSection.getSubpart().getId()) {
if (iFilter.match(enrollment.getCourse(), section)) {
match = true;
break;
}
}
if (section.getSubpart().getConfig().getId() != iSelectedSection.getSubpart().getConfig().getId() && section.getSubpart().getInstructionalType().equals(iSelectedSection.getSubpart().getInstructionalType())) {
if (iFilter.match(enrollment.getCourse(), section)) {
match = true;
break;
}
}
} else {
if (iFilter.match(enrollment.getCourse(), section)) {
match = true;
break;
}
}
}
if (!match)
i.remove();
}
}
}
if (request.equals(iSelectedRequest))
iMatched = values.size();
return values;
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class SuggestionsBranchAndBound method backtrack.
/**
* Main branch and bound rutine
* @param requests2resolve remaining requests to assign
* @param altRequests2resolve alternative requests to assign
* @param idx current depth
* @param depth remaining depth
* @param alt can leave a request unassigned
*/
protected void backtrack(ArrayList<Request> requests2resolve, TreeSet<Request> altRequests2resolve, int idx, int depth, boolean alt) {
if (!iTimeoutReached && iTimeout > 0 && System.currentTimeMillis() - iT0 > iTimeout)
iTimeoutReached = true;
int nrUnassigned = requests2resolve.size() - idx;
if (nrUnassigned == 0) {
List<FreeTimeRequest> okFreeTimes = new ArrayList<FreeTimeRequest>();
double sectionsWithPenalty = 0;
for (Request r : iStudent.getRequests()) {
Enrollment e = iAssignment.getValue(r);
if (iMaxSectionsWithPenalty >= 0 && e != null && r instanceof CourseRequest) {
for (Section s : e.getSections()) sectionsWithPenalty += iModel.getOverExpected(iAssignment, s, r);
}
if (e == null && r instanceof FreeTimeRequest) {
FreeTimeRequest ft = (FreeTimeRequest) r;
Enrollment enrollment = ft.createEnrollment();
if (iModel.conflictValues(iAssignment, enrollment).isEmpty()) {
iAssignment.assign(0, enrollment);
okFreeTimes.add(ft);
}
}
if (e != null && e.isCourseRequest() && e.getSections().isEmpty()) {
Double minPenalty = null;
for (Enrollment other : values(e.getRequest())) {
if (!isAllowed(other))
continue;
if (e.equals(other))
continue;
double penalty = 0.0;
for (Section s : other.getSections()) penalty += iModel.getOverExpected(iAssignment, s, other.getRequest());
if (minPenalty == null || minPenalty > penalty)
minPenalty = penalty;
if (minPenalty == 0.0)
break;
}
if (minPenalty != null)
sectionsWithPenalty += minPenalty;
}
}
if (iMaxSectionsWithPenalty >= 0 && sectionsWithPenalty > iMaxSectionsWithPenalty)
return;
Suggestion s = new Suggestion(requests2resolve);
if (iSuggestions.size() >= iMaxSuggestions && iSuggestions.last().compareTo(s) <= 0)
return;
if (iMatched != 1) {
for (Iterator<Suggestion> i = iSuggestions.iterator(); i.hasNext(); ) {
Suggestion x = i.next();
if (x.sameSelectedSection()) {
if (x.compareTo(s) <= 0)
return;
i.remove();
}
}
}
s.init();
iSuggestions.add(s);
if (iSuggestions.size() > iMaxSuggestions)
iSuggestions.remove(iSuggestions.last());
for (FreeTimeRequest ft : okFreeTimes) iAssignment.unassign(0, ft);
return;
}
if (!canContinue(requests2resolve, idx, depth))
return;
Request request = requests2resolve.get(idx);
for (Enrollment enrollment : values(request)) {
if (!canContinueEvaluation())
break;
if (!isAllowed(enrollment))
continue;
if (enrollment.equals(iAssignment.getValue(request)))
continue;
if (enrollment.getAssignments().isEmpty() && alt)
continue;
Set<Enrollment> conflicts = iModel.conflictValues(iAssignment, enrollment);
if (!checkBound(requests2resolve, idx, depth, enrollment, conflicts))
continue;
Enrollment current = iAssignment.getValue(request);
ArrayList<Request> newVariables2resolve = new ArrayList<Request>(requests2resolve);
for (Iterator<Enrollment> i = conflicts.iterator(); i.hasNext(); ) {
Enrollment conflict = i.next();
iAssignment.unassign(0, conflict.variable());
if (!newVariables2resolve.contains(conflict.variable()))
newVariables2resolve.add(conflict.variable());
}
if (current != null)
iAssignment.unassign(0, current.variable());
iAssignment.assign(0, enrollment);
if (enrollment.getAssignments().isEmpty()) {
if (altRequests2resolve != null && !altRequests2resolve.isEmpty()) {
Suggestion lastBefore = (iSuggestions.isEmpty() ? null : iSuggestions.last());
int sizeBefore = iSuggestions.size();
for (Request r : altRequests2resolve) {
newVariables2resolve.add(r);
backtrack(newVariables2resolve, null, idx + 1, depth, true);
newVariables2resolve.remove(r);
}
Suggestion lastAfter = (iSuggestions.isEmpty() ? null : iSuggestions.last());
int sizeAfter = iSuggestions.size();
// did not succeeded with an alternative -> try without it
if (sizeBefore == sizeAfter && (sizeAfter < iMaxSuggestions || sizeAfter == 0 || lastAfter.compareTo(lastBefore) == 0))
backtrack(newVariables2resolve, altRequests2resolve, idx + 1, depth - 1, alt);
} else {
backtrack(newVariables2resolve, altRequests2resolve, idx + 1, depth - 1, alt);
}
} else {
backtrack(newVariables2resolve, altRequests2resolve, idx + 1, depth - 1, alt);
}
if (current == null)
iAssignment.unassign(0, request);
else
iAssignment.assign(0, current);
for (Iterator<Enrollment> i = conflicts.iterator(); i.hasNext(); ) {
Enrollment conflict = i.next();
iAssignment.assign(0, conflict);
}
}
}
use of org.cpsolver.studentsct.model.CourseRequest in project cpsolver by UniTime.
the class AccommodationConflictsTable 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(final Assignment<Request, Enrollment> assignment, boolean includeLastLikeStudents, boolean includeRealStudents, boolean useAmPm) {
if (iSQ == null)
throw new IllegalArgumentException("Student Schedule Quality is not enabled.");
CSVFile csv = new CSVFile();
csv.setHeader(new CSVFile.CSVField[] { new CSVFile.CSVField("__Student"), new CSVFile.CSVField("External Id"), new CSVFile.CSVField("Student Name"), new CSVFile.CSVField("Curriculum"), new CSVFile.CSVField("Group"), new CSVFile.CSVField("Advisor"), new CSVFile.CSVField("Type"), new CSVFile.CSVField("Course"), new CSVFile.CSVField("Class"), new CSVFile.CSVField("Meeting Time"), new CSVFile.CSVField("Room"), new CSVFile.CSVField("Conflicting\nCourse"), new CSVFile.CSVField("Conflicting\nClass"), new CSVFile.CSVField("Conflicting\nMeeting Time"), new CSVFile.CSVField("Conflicting\nRoom"), new CSVFile.CSVField("Penalty\nMinutes") });
List<Conflict> confs = new ArrayList<Conflict>();
for (Request r1 : getModel().variables()) {
Enrollment e1 = assignment.getValue(r1);
if (e1 == null || !(r1 instanceof CourseRequest))
continue;
for (StudentQuality.Type t : iTypes) confs.addAll(iSQ.conflicts(t, e1));
for (Request r2 : r1.getStudent().getRequests()) {
Enrollment e2 = assignment.getValue(r2);
if (e2 == null || r1.getId() >= r2.getId() || !(r2 instanceof CourseRequest))
continue;
for (StudentQuality.Type t : iTypes) confs.addAll(iSQ.conflicts(t, e1, e2));
}
}
Collections.sort(confs, new Comparator<Conflict>() {
@Override
public int compare(Conflict c1, Conflict c2) {
int cmp = (c1.getStudent().getExternalId() == null ? "" : c1.getStudent().getExternalId()).compareTo(c2.getStudent().getExternalId() == null ? "" : c2.getStudent().getExternalId());
if (cmp != 0)
return cmp;
cmp = c1.getStudent().compareTo(c2.getStudent());
if (cmp != 0)
return cmp;
if (c1.getType() != c2.getType())
return Integer.compare(c1.getType().ordinal(), c2.getType().ordinal());
cmp = c1.getE1().getCourse().getName().toString().compareTo(c2.getE1().getCourse().getName());
if (cmp != 0)
return cmp;
return ((Section) c1.getS1()).getName(c1.getE1().getCourse().getId()).compareTo(((Section) c2.getS1()).getName(c2.getE1().getCourse().getId()));
}
});
for (Conflict conflict : confs) {
if (conflict.getStudent().isDummy() && !includeLastLikeStudents)
continue;
if (!conflict.getStudent().isDummy() && !includeRealStudents)
continue;
if (conflict.getType() == Type.AccBackToBack) {
boolean trueConflict = false;
for (int i = 0; i < Constants.DAY_CODES.length; i++) {
if ((conflict.getS1().getTime().getDayCode() & Constants.DAY_CODES[i]) == 0 || (conflict.getS2().getTime().getDayCode() & Constants.DAY_CODES[i]) == 0)
continue;
boolean inBetween = false;
for (Request r : conflict.getStudent().getRequests()) {
Enrollment e = r.getAssignment(assignment);
if (e == null)
continue;
for (SctAssignment s : e.getAssignments()) {
if (s.getTime() == null)
continue;
if ((s.getTime().getDayCode() & Constants.DAY_CODES[i]) == 0)
continue;
if (!s.getTime().shareWeeks(conflict.getS1().getTime()) || !s.getTime().shareWeeks(conflict.getS2().getTime()))
continue;
if (conflict.getS1().getTime().getStartSlot() + conflict.getS1().getTime().getLength() <= s.getTime().getStartSlot() && s.getTime().getStartSlot() + s.getTime().getLength() <= conflict.getS2().getTime().getStartSlot()) {
inBetween = true;
break;
}
if (conflict.getS2().getTime().getStartSlot() + conflict.getS2().getTime().getLength() <= s.getTime().getStartSlot() && s.getTime().getStartSlot() + s.getTime().getLength() <= conflict.getS1().getTime().getStartSlot()) {
inBetween = true;
break;
}
}
}
if (!inBetween) {
trueConflict = true;
break;
}
}
if (!trueConflict)
continue;
}
List<CSVFile.CSVField> line = new ArrayList<CSVFile.CSVField>();
line.add(new CSVFile.CSVField(conflict.getStudent().getId()));
line.add(new CSVFile.CSVField(conflict.getStudent().getExternalId()));
line.add(new CSVFile.CSVField(conflict.getStudent().getName()));
line.add(new CSVFile.CSVField(curriculum(conflict.getStudent())));
line.add(new CSVFile.CSVField(group(conflict.getStudent())));
line.add(new CSVFile.CSVField(advisor(conflict.getStudent())));
switch(conflict.getType()) {
case ShortDistance:
line.add(new CSVFile.CSVField(iSQ.getDistanceMetric().getShortDistanceAccommodationReference()));
break;
case AccBackToBack:
line.add(new CSVFile.CSVField(iSQ.getStudentQualityContext().getBackToBackAccommodation()));
break;
case AccBreaksBetweenClasses:
line.add(new CSVFile.CSVField(iSQ.getStudentQualityContext().getBreakBetweenClassesAccommodation()));
break;
case AccFreeTimeOverlap:
line.add(new CSVFile.CSVField(iSQ.getStudentQualityContext().getFreeTimeAccommodation()));
break;
default:
line.add(new CSVFile.CSVField(conflict.getType().getName()));
break;
}
line.add(new CSVFile.CSVField(conflict.getE1().getCourse().getName()));
line.add(new CSVFile.CSVField(conflict.getS1() instanceof Section ? ((Section) conflict.getS1()).getName(conflict.getE1().getCourse().getId()) : ""));
line.add(new CSVFile.CSVField(conflict.getS1().getTime() == null ? "" : conflict.getS1().getTime().getLongName(useAmPm)));
line.add(new CSVFile.CSVField(rooms(conflict.getS1())));
line.add(new CSVFile.CSVField(conflict.getE2().isCourseRequest() ? conflict.getE2().getCourse().getName() : "Free Time"));
line.add(new CSVFile.CSVField(conflict.getS2() instanceof Section ? ((Section) conflict.getS2()).getName(conflict.getE2().getCourse().getId()) : ""));
line.add(new CSVFile.CSVField(conflict.getS2().getTime() == null ? "" : conflict.getS2().getTime().getLongName(useAmPm)));
line.add(new CSVFile.CSVField(rooms(conflict.getS2())));
switch(conflict.getType()) {
case AccFreeTimeOverlap:
line.add(new CSVFile.CSVField(5 * conflict.getPenalty()));
break;
case ShortDistance:
line.add(new CSVFile.CSVField(iSQ.getStudentQualityContext().getDistanceInMinutes(((Section) conflict.getS1()).getPlacement(), ((Section) conflict.getS2()).getPlacement())));
break;
case AccBackToBack:
case AccBreaksBetweenClasses:
TimeLocation t1 = conflict.getS1().getTime();
TimeLocation t2 = conflict.getS2().getTime();
if (t1.getStartSlot() + t1.getNrSlotsPerMeeting() <= t2.getStartSlot()) {
int dist = t2.getStartSlot() - (t1.getStartSlot() + t1.getNrSlotsPerMeeting());
line.add(new CSVFile.CSVField(5 * dist + t1.getBreakTime()));
} else if (t2.getStartSlot() + t2.getNrSlotsPerMeeting() <= t1.getStartSlot()) {
int dist = t1.getStartSlot() - (t2.getStartSlot() + t2.getNrSlotsPerMeeting());
line.add(new CSVFile.CSVField(5 * dist + t2.getBreakTime()));
} else {
line.add(new CSVFile.CSVField(null));
}
break;
default:
line.add(new CSVFile.CSVField(conflict.getPenalty()));
break;
}
csv.addLine(line);
}
return csv;
}
Aggregations