Permalink
Browse files

Batch Student Sectioning Solver

 - section / config unreserved space in limit constraints: use the same technique to overcome rounding problems as for the section / config limit
   - that is adding a little less than the biggest request weight (of the section / config) to the unreserved space

git-svn-id: http://cpsolver.googlecode.com/svn/trunk@545 e5151b7e-cabb-5534-7ab8-ba89a8838d1f
  • Loading branch information...
1 parent b202406 commit 0eb7de78616015f98004bf83222367c5a9893a83 muller@unitime.org committed May 24, 2011
@@ -59,6 +59,7 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/
public class ReservationLimit extends GlobalConstraint<Request, Enrollment> {
+ private static double sNominalWeight = 0.00001;
private boolean iPreferDummyStudents = false;
/**
@@ -72,6 +73,26 @@ public ReservationLimit(DataProperties cfg) {
iPreferDummyStudents = cfg.getPropertyBoolean("ReservationLimit.PreferDummyStudents", false);
}
+
+ /**
+ * Remaining unreserved space in a config if the given request is assigned. In order
+ * to overcome rounding problems with last-like students ( e.g., 5 students
+ * are projected to two sections of limit 2 -- each section can have up to 3
+ * of these last-like students), the weight of the request with the highest
+ * weight in the section is changed to a small nominal weight.
+ *
+ * @param config
+ * a config that is of concern
+ * @param request
+ * a request of a student to be assigned containing the given
+ * section
+ * @return config's new unreserved space
+ */
+ public static double getUnreservedSpace(Config config, Request request) {
+ return config.getUnreservedSpace(request) - request.getWeight()
+ + Math.max(config.getMaxEnrollmentWeight(), request.getWeight()) - sNominalWeight;
+ }
+
/**
* A given enrollment is conflicting, if the reservation's remaning available space
@@ -180,9 +201,9 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
return;
}
- double unreserved = config.getUnreservedSpace(enrollment.getRequest());
+ double unreserved = getUnreservedSpace(config, enrollment.getRequest());
- if (unreserved < enrollment.getRequest().getWeight()) {
+ if (unreserved < 0.0) {
// no unreserved space available -> cannot be assigned
// try to unassign some other enrollments that also do not have config reservation
@@ -198,7 +219,7 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
adepts.add(e);
}
- while (unreserved < enrollment.getRequest().getWeight()) {
+ while (unreserved < 0.0) {
if (adepts.isEmpty()) {
// no adepts -> enrollment cannot be assigned
conflicts.add(enrollment);
@@ -252,10 +273,10 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
// check configuration unavailable space too
double unreserved = Math.min(
- config.getOffering().getUnreservedSpace(enrollment.getRequest()),
- config.getUnreservedSpace(enrollment.getRequest()));
+ config.getOffering().getUnreservedSpace(enrollment.getRequest()) - enrollment.getRequest().getWeight(),
+ getUnreservedSpace(config, enrollment.getRequest()));
- if (unreserved < enrollment.getRequest().getWeight()) {
+ if (unreserved < 0.0) {
// no unreserved space available -> cannot be assigned
// try to unassign some other enrollments that also do not have reservation
@@ -271,7 +292,7 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
adepts.add(e);
}
- while (unreserved < enrollment.getRequest().getWeight()) {
+ while (unreserved < 0.0) {
if (adepts.isEmpty()) {
// no adepts -> enrollment cannot be assigned
conflicts.add(enrollment);
@@ -364,12 +385,12 @@ public boolean inConflict(Enrollment enrollment) {
// if not configuration reservation, check configuration unreserved space too
return (!hasConfigReservation(enrollment) &&
- config.getUnreservedSpace(enrollment.getRequest()) < enrollment.getRequest().getWeight());
+ getUnreservedSpace(config, enrollment.getRequest()) < 0.0);
} else {
// check unreserved space;
return config.getOffering().getTotalUnreservedSpace() < enrollment.getRequest().getWeight() ||
config.getTotalUnreservedSpace() < enrollment.getRequest().getWeight() ||
- config.getUnreservedSpace(enrollment.getRequest()) < enrollment.getRequest().getWeight() ||
+ getUnreservedSpace(config, enrollment.getRequest()) < 0.0 ||
config.getOffering().getUnreservedSpace(enrollment.getRequest()) < enrollment.getRequest().getWeight();
}
}
@@ -101,6 +101,26 @@ public static double getEnrollmentWeight(Section section, Request request) {
}
/**
+ * Remaining unreserved space in a section if the given request is assigned. In order
+ * to overcome rounding problems with last-like students ( e.g., 5 students
+ * are projected to two sections of limit 2 -- each section can have up to 3
+ * of these last-like students), the weight of the request with the highest
+ * weight in the section is changed to a small nominal weight.
+ *
+ * @param section
+ * a section that is of concern
+ * @param request
+ * a request of a student to be assigned containing the given
+ * section
+ * @return section's new unreserved space
+ */
+ public static double getUnreservedSpace(Section section, Request request) {
+ return section.getUnreservedSpace(request) - request.getWeight()
+ + Math.max(section.getMaxEnrollmentWeight(), request.getWeight()) - sNominalWeight;
+ }
+
+
+ /**
* True if the enrollment has reservation for this section.
* Everything else is checked in the {@link ReservationLimit} constraint.
**/
@@ -137,18 +157,18 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
// for each section
for (Section section : enrollment.getSections()) {
-
+
// no reservation -- check the space in the unreserved space in the section
- if (!hasSectionReservation(enrollment, section)) {
+ if (enrollment.getConfig().getOffering().hasReservations() && !hasSectionReservation(enrollment, section)) {
// section is fully reserved by section reservations
if (section.getTotalUnreservedSpace() < enrollment.getRequest().getWeight()) {
conflicts.add(enrollment);
return;
}
- double unreserved = section.getUnreservedSpace(enrollment.getRequest());
+ double unreserved = getUnreservedSpace(section, enrollment.getRequest());
- if (unreserved < enrollment.getRequest().getWeight()) {
+ if (unreserved < 0.0) {
// no unreserved space available -> cannot be assigned
// try to unassign some other enrollments that also do not have reservation
@@ -164,7 +184,7 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
adepts.add(e);
}
- while (unreserved < enrollment.getRequest().getWeight()) {
+ while (unreserved < 0.0) {
if (adepts.isEmpty()) {
// no adepts -> enrollment cannot be assigned
conflicts.add(enrollment);
@@ -206,7 +226,6 @@ public void computeConflicts(Enrollment enrollment, Set<Enrollment> conflicts) {
conflicts.add(conflict);
}
}
-
}
// unlimited section
@@ -317,16 +336,17 @@ public boolean inConflict(Enrollment enrollment) {
// for each section
for (Section section : enrollment.getSections()) {
- // unlimited section
- if (section.getLimit() < 0)
- continue;
-
// not have reservation -> check unreserved space
- if (!hasSectionReservation(enrollment, section) && (
+ if (enrollment.getConfig().getOffering().hasReservations() &&
+ !hasSectionReservation(enrollment, section) && (
section.getTotalUnreservedSpace() < enrollment.getRequest().getWeight() ||
- section.getUnreservedSpace(enrollment.getRequest()) < enrollment.getRequest().getWeight()))
+ getUnreservedSpace(section, enrollment.getRequest()) < 0.0))
return true;
+ // unlimited section
+ if (section.getLimit() < 0)
+ continue;
+
// new enrollment weight
double enrlWeight = getEnrollmentWeight(section, enrollment.getRequest());

0 comments on commit 0eb7de7

Please sign in to comment.