Skip to content

Commit

Permalink
Course Timetabling Model
Browse files Browse the repository at this point in the history
- added an ability to change whether student sectioning informations are saved/restored with best solution
  - methods isOnFlySectioningEnabled(), setOnFlySectioningEnabled(boolean)
- restore best: when on-fly sectioning is enabled, considerably speed up restore best solution
  (when there are a lot of jenrl constraints that can be removed as students have been moved avay of the appropriate class pairs)
- student conflict criteria (getStudentConflictCriteria()) moved from StudentSwapSectioning to TimetableModel
  • Loading branch information
tomas-muller committed Nov 8, 2024
1 parent 88e2efd commit 4a5e677
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 14 deletions.
54 changes: 53 additions & 1 deletion src/org/cpsolver/coursett/model/TimetableModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.BitSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
Expand Down Expand Up @@ -105,6 +106,9 @@ public class TimetableModel extends ConstantModel<Lecture, Placement> {

private StudentSectioning iStudentSectioning = null;
private List<StudentGroup> iStudentGroups = new ArrayList<StudentGroup>();

private boolean iUseCriteria = true;
private List<StudentConflict> iStudentConflictCriteria = null;

@SuppressWarnings("unchecked")
public TimetableModel(DataProperties properties) {
Expand Down Expand Up @@ -188,7 +192,7 @@ else if (properties.getPropertyBoolean("General.AllowProhibitedRooms", false)) {
sLogger.error("Unable to use " + constraint + ": " + e.getMessage());
}
}

iUseCriteria = properties.getPropertyBoolean("SctSectioning.UseCriteria", true);
}

public DistanceMetric getDistanceMetric() {
Expand Down Expand Up @@ -663,6 +667,24 @@ public void restoreBest(Assignment<Lecture, Placement> assignment) {
}
}
// remove empty joint enrollments
for (Iterator<JenrlConstraint> i = iJenrlConstraints.iterator(); i.hasNext(); ) {
JenrlConstraint jenrl = i.next();
if (jenrl.getNrStudents() == 0) {
jenrl.getContext(assignment).unassigned(assignment, null);
Object[] vars = jenrl.variables().toArray();
for (int k = 0; k < vars.length; k++)
jenrl.removeVariable((Lecture) vars[k]);
i.remove();
}
}
for (Iterator<Constraint<Lecture, Placement>> i = constraints().iterator(); i.hasNext(); ) {
Constraint<Lecture, Placement> c = i.next();
if (c instanceof JenrlConstraint && ((JenrlConstraint)c).getNrStudents() == 0) {
removeReference((JenrlConstraint)c);
i.remove();
}
}
/*
for (JenrlConstraint jenrl: new ArrayList<JenrlConstraint>(getJenrlConstraints())) {
if (jenrl.getNrStudents() == 0) {
jenrl.getContext(assignment).unassigned(assignment, null);
Expand All @@ -672,9 +694,39 @@ public void restoreBest(Assignment<Lecture, Placement> assignment) {
removeConstraint(jenrl);
}
}
*/
}
super.restoreBest(assignment);
}

public boolean isAllowBreakHard() { return iAllowBreakHard; }

public boolean isOnFlySectioningEnabled() { return iOnFlySectioning; }
public void setOnFlySectioningEnabled(boolean onFlySectioning) { iOnFlySectioning = onFlySectioning; }

@Override
public void addCriterion(Criterion<Lecture, Placement> criterion) {
super.addCriterion(criterion);
iStudentConflictCriteria = null;
}

@Override
public void removeCriterion(Criterion<Lecture, Placement> criterion) {
super.removeCriterion(criterion);
iStudentConflictCriteria = null;
}

/**
* List of student conflict criteria
*/
public List<StudentConflict> getStudentConflictCriteria() {
if (!iUseCriteria) return null;
if (iStudentConflictCriteria == null) {
iStudentConflictCriteria = new ArrayList<StudentConflict>();
for (Criterion<Lecture, Placement> criterion: getCriteria())
if (criterion instanceof StudentConflict)
iStudentConflictCriteria.add((StudentConflict)criterion);
}
return iStudentConflictCriteria;
}
}
15 changes: 2 additions & 13 deletions src/org/cpsolver/coursett/sectioning/StudentSwapSectioning.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.cpsolver.coursett.sectioning;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
Expand All @@ -22,7 +21,6 @@
import org.cpsolver.coursett.model.TimetableModel;
import org.cpsolver.coursett.sectioning.SctSectioning.GroupBasedInitialSectioning;
import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.criteria.Criterion;
import org.cpsolver.ifs.model.InfoProvider;
import org.cpsolver.ifs.model.Neighbour;
import org.cpsolver.ifs.solution.Solution;
Expand Down Expand Up @@ -54,28 +52,19 @@
* <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
*/
public class StudentSwapSectioning extends DefaultStudentSectioning implements InfoProvider<Lecture, Placement> {
List<StudentConflict> iStudentConflictCriteria = null;
private static double sEps = 0.0001;
private double iGroupWeight = 0.1;
private boolean iUseCriteria = true;
private int iMaxIdleResection = 1000;

public StudentSwapSectioning(TimetableModel model) {
super(model);
iUseCriteria = model.getProperties().getPropertyBoolean("StudentSwaps.UseCriteria", true);
iGroupWeight = model.getProperties().getPropertyDouble("StudentSwaps.GroupWeight", 10.0);
iMaxIdleResection = model.getProperties().getPropertyInt("StudentSwaps.MaxIdleResection", 1000);
}

protected List<StudentConflict> getStudentConflictCriteria() {
if (!iUseCriteria) return null;
if (iStudentConflictCriteria == null && iModel != null) {
iStudentConflictCriteria = new ArrayList<StudentConflict>();
for (Criterion<Lecture, Placement> criterion: iModel.getCriteria())
if (criterion instanceof StudentConflict)
iStudentConflictCriteria.add((StudentConflict)criterion);
}
return iStudentConflictCriteria;
if (iModel != null) return iModel.getStudentConflictCriteria();
return null;
}

@Override
Expand Down

0 comments on commit 4a5e677

Please sign in to comment.