use of org.cpsolver.coursett.model.TimetableModel in project cpsolver by UniTime.
the class StudentSwapSectioning method switchStudents.
@Override
public void switchStudents(Solution<Lecture, Placement> solution, TerminationCondition<Lecture, Placement> termination) {
long it = 0, lastImp = 0;
double t0 = JProf.currentTimeMillis();
DataProperties cfg = ((TimetableModel) solution.getModel()).getProperties();
long maxIdle = cfg.getPropertyInt("StudentSwaps.MaxIdle", 100000);
getProgress().setStatus("Student Sectioning...");
getProgress().info("Student Conflicts: " + sDF2.format(objective(solution)) + " (group: " + sDF2.format(gp(solution)) + "%)");
getProgress().setPhase("Swapping students [HC]...", 1000);
StudentSwapGenerator g = new StudentSwapGenerator();
while ((it - lastImp) < maxIdle && (termination == null || termination.canContinue(solution))) {
it++;
if ((it % 1000) == 0) {
long prg = Math.round(1000.0 * (it - lastImp) / maxIdle);
if (getProgress().getProgress() < prg)
getProgress().setProgress(prg);
if ((it % 10000) == 0)
getProgress().info("Iter=" + (it / 1000) + "k, Idle=" + sDF2.format((it - lastImp) / 1000.0) + "k, Speed=" + sDF2.format(1000.0 * it / (JProf.currentTimeMillis() - t0)) + " it/s" + ", Value=" + sDF2.format(value(solution)) + ", Objective=" + sDF2.format(objective(solution)) + ", Group=" + sDF2.format(gp(solution)) + "%");
}
Neighbour<Lecture, Placement> n = g.selectNeighbour(solution);
if (n == null)
continue;
double v = value(n, solution.getAssignment());
if (v < -sEps) {
lastImp = it;
}
if (v <= 0) {
n.assign(solution.getAssignment(), it);
}
}
getProgress().info("Student Conflicts: " + sDF2.format(objective(solution)) + " (group: " + sDF2.format(gp(solution)) + "%)");
double f = cfg.getPropertyDouble("StudentSwaps.Deluge.Factor", 0.9999999);
double ub = cfg.getPropertyDouble("StudentSwaps.Deluge.UpperBound", 1.10);
double lb = cfg.getPropertyDouble("StudentSwaps.Deluge.LowerBound", 0.90);
double total = value(solution);
double bound = ub * total;
double best = total;
it = 0;
lastImp = 0;
t0 = JProf.currentTimeMillis();
getProgress().setPhase("Swapping students [GD]...", 1000);
while (bound > lb * total && total > 0 && (termination == null || termination.canContinue(solution))) {
Neighbour<Lecture, Placement> n = g.selectNeighbour(solution);
if (n != null) {
double value = value(n, solution.getAssignment());
if (value < 0) {
lastImp = it;
}
if (value <= 0.0 || total + value < bound) {
n.assign(solution.getAssignment(), it);
if (total + value < best) {
best = total + value;
}
total += value;
}
}
bound *= f;
it++;
if ((it % 1000) == 0) {
long prg = 1000 - Math.round(1000.0 * (bound - lb * best) / (ub * best - lb * best));
if (getProgress().getProgress() < prg)
getProgress().setProgress(prg);
if ((it % 10000) == 0) {
getProgress().info("Iter=" + (it / 1000) + "k, Idle=" + sDF2.format((it - lastImp) / 1000.0) + "k, Speed=" + sDF2.format(1000.0 * it / (JProf.currentTimeMillis() - t0)) + " it/s" + ", Value=" + sDF2.format(value(solution)) + ", Objective=" + sDF2.format(objective(solution)) + ", Group=" + sDF2.format(gp(solution)) + "%");
getProgress().info("Bound is " + sDF2.format(bound) + ", " + "best value is " + sDF2.format(best) + " (" + sDF2.format(100.0 * bound / best) + "%), " + "current value is " + sDF2.format(total) + " (" + sDF2.format(100.0 * bound / total) + "%)");
}
}
}
getProgress().info("Student Conflicts: " + sDF2.format(objective(solution)) + " (group: " + sDF2.format(gp(solution)) + "%)");
}
use of org.cpsolver.coursett.model.TimetableModel in project cpsolver by UniTime.
the class GroupConstraint method computeConflicts.
public void computeConflicts(Assignment<Lecture, Placement> assignment, Placement value, Set<Placement> conflicts, boolean fwdCheck) {
if (!isHard())
return;
for (Lecture v : variables()) {
if (v.equals(value.variable()))
// ignore this variable
continue;
Placement p = assignment.getValue(v);
if (p == null)
// there is an unassigned variable -- great, still a chance to get violated
continue;
if (!isSatisfiedPair(assignment, p, value))
conflicts.add(p);
}
if (getType().is(Flag.BACK_TO_BACK)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(value.variable(), value);
if (!isSatisfiedSeq(assignment, assignments, conflicts))
conflicts.add(value);
}
if (getType().is(Flag.MAX_HRS_DAY)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(value.variable(), value);
for (int dayCode : Constants.DAY_CODES) {
if (iMaxNHoursADayConsiderDatePatterns) {
for (BitSet week : ((TimetableModel) getModel()).getWeeks()) {
if (!value.getTimeLocation().shareWeeks(week))
continue;
if (nrSlotsADay(assignment, dayCode, week, assignments, conflicts) > getType().getMax()) {
List<Placement> adepts = new ArrayList<Placement>();
for (Lecture l : variables()) {
if (l.equals(value.variable()) || l.isConstant())
continue;
Placement p = assignment.getValue(l);
if (p == null || conflicts.contains(p) || p.getTimeLocation() == null)
continue;
if ((p.getTimeLocation().getDayCode() & dayCode) == 0 || !p.getTimeLocation().shareWeeks(week))
continue;
adepts.add(p);
}
do {
if (adepts.isEmpty()) {
conflicts.add(value);
break;
}
Placement conflict = ToolBox.random(adepts);
adepts.remove(conflict);
conflicts.add(conflict);
} while (nrSlotsADay(assignment, dayCode, week, assignments, conflicts) > getType().getMax());
}
}
} else {
if (nrSlotsADay(assignment, dayCode, null, assignments, conflicts) > getType().getMax()) {
List<Placement> adepts = new ArrayList<Placement>();
for (Lecture l : variables()) {
if (l.equals(value.variable()) || l.isConstant())
continue;
Placement p = assignment.getValue(l);
if (p == null || conflicts.contains(p) || p.getTimeLocation() == null)
continue;
if ((p.getTimeLocation().getDayCode() & dayCode) == 0)
continue;
adepts.add(p);
}
do {
if (adepts.isEmpty()) {
conflicts.add(value);
break;
}
Placement conflict = ToolBox.random(adepts);
adepts.remove(conflict);
conflicts.add(conflict);
} while (nrSlotsADay(assignment, dayCode, null, assignments, conflicts) > getType().getMax());
}
}
}
}
// Forward checking
if (fwdCheck)
forwardCheck(assignment, value, conflicts, new HashSet<GroupConstraint>(), iForwardCheckMaxDepth - 1);
}
use of org.cpsolver.coursett.model.TimetableModel in project cpsolver by UniTime.
the class GroupConstraint method setModel.
@Override
public void setModel(Model<Lecture, Placement> model) {
super.setModel(model);
if (model != null) {
DataProperties config = ((TimetableModel) model).getProperties();
iDayOfWeekOffset = config.getPropertyInt("DatePattern.DayOfWeekOffset", 0);
iPrecedenceConsiderDatePatterns = config.getPropertyBoolean("Precedence.ConsiderDatePatterns", true);
iForwardCheckMaxDepth = config.getPropertyInt("ForwardCheck.MaxDepth", iForwardCheckMaxDepth);
iForwardCheckMaxDomainSize = config.getPropertyInt("ForwardCheck.MaxDomainSize", iForwardCheckMaxDomainSize);
iMaxNHoursADayConsiderDatePatterns = config.getPropertyBoolean("MaxNHoursADay.ConsiderDatePatterns", iMaxNHoursADayConsiderDatePatterns);
iNrWorkDays = (config.getPropertyInt("General.LastWorkDay", 4) - config.getPropertyInt("General.FirstWorkDay", 0) + 1);
}
}
use of org.cpsolver.coursett.model.TimetableModel in project cpsolver by UniTime.
the class GroupConstraint method getCurrentPreference.
/** Current constraint preference change (if given placement is assigned)
* @param assignment current assignment
* @param placement placement that is being considered
* @return change in the current preference, if assigned
**/
public int getCurrentPreference(Assignment<Lecture, Placement> assignment, Placement placement) {
// no preference
if (isHard())
return 0;
// not enough variable
if (countAssignedVariables(assignment) + (assignment.getValue(placement.variable()) == null ? 1 : 0) < 2)
return 0;
if (getType().is(Flag.MAX_HRS_DAY)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(placement.variable(), placement);
HashMap<Lecture, Placement> unassignments = new HashMap<Lecture, Placement>();
unassignments.put(placement.variable(), null);
int after = 0;
int before = 0;
for (int dayCode : Constants.DAY_CODES) {
if (iMaxNHoursADayConsiderDatePatterns) {
for (BitSet week : ((TimetableModel) getModel()).getWeeks()) {
after += Math.max(0, nrSlotsADay(assignment, dayCode, week, assignments, null) - getType().getMax());
before += Math.max(0, nrSlotsADay(assignment, dayCode, week, unassignments, null) - getType().getMax());
}
} else {
after += Math.max(0, nrSlotsADay(assignment, dayCode, null, assignments, null) - getType().getMax());
before += Math.max(0, nrSlotsADay(assignment, dayCode, null, unassignments, null) - getType().getMax());
}
}
return (after > 0 ? Math.abs(iPreference) * after / 12 : -Math.abs(iPreference)) - (before > 0 ? Math.abs(iPreference) * before / 12 : -Math.abs(iPreference));
}
int nrViolatedPairsAfter = 0;
int nrViolatedPairsBefore = 0;
for (Lecture v1 : variables()) {
for (Lecture v2 : variables()) {
if (v1.getId() >= v2.getId())
continue;
Placement p1 = (v1.equals(placement.variable()) ? null : assignment.getValue(v1));
Placement p2 = (v2.equals(placement.variable()) ? null : assignment.getValue(v2));
if (p1 != null && p2 != null && !isSatisfiedPair(assignment, p1, p2))
nrViolatedPairsBefore++;
if (v1.equals(placement.variable()))
p1 = placement;
if (v2.equals(placement.variable()))
p2 = placement;
if (p1 != null && p2 != null && !isSatisfiedPair(assignment, p1, p2))
nrViolatedPairsAfter++;
}
}
if (getType().is(Flag.BACK_TO_BACK)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(placement.variable(), placement);
Set<Placement> conflicts = new HashSet<Placement>();
if (isSatisfiedSeq(assignment, assignments, conflicts))
nrViolatedPairsAfter += conflicts.size();
else
nrViolatedPairsAfter = variables().size();
HashMap<Lecture, Placement> unassignments = new HashMap<Lecture, Placement>();
unassignments.put(placement.variable(), null);
Set<Placement> previous = new HashSet<Placement>();
if (isSatisfiedSeq(assignment, unassignments, previous))
nrViolatedPairsBefore += previous.size();
else
nrViolatedPairsBefore = variables().size();
}
return (nrViolatedPairsAfter > 0 ? Math.abs(iPreference) * nrViolatedPairsAfter : -Math.abs(iPreference)) - (nrViolatedPairsBefore > 0 ? Math.abs(iPreference) * nrViolatedPairsBefore : -Math.abs(iPreference));
}
use of org.cpsolver.coursett.model.TimetableModel in project cpsolver by UniTime.
the class GroupConstraint method isConsistent.
@Override
public boolean isConsistent(Placement value1, Placement value2) {
if (!isHard())
return true;
if (!isSatisfiedPair(null, value1, value2))
return false;
if (getType().is(Flag.BACK_TO_BACK)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(value1.variable(), value1);
assignments.put(value2.variable(), value2);
if (!isSatisfiedSeq(null, assignments, null))
return false;
}
if (getType().is(Flag.MAX_HRS_DAY)) {
HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
assignments.put(value1.variable(), value1);
assignments.put(value2.variable(), value2);
for (int dayCode : Constants.DAY_CODES) {
if (iMaxNHoursADayConsiderDatePatterns) {
for (BitSet week : ((TimetableModel) getModel()).getWeeks()) {
if (!value1.getTimeLocation().shareWeeks(week) && !value2.getTimeLocation().shareWeeks(week))
continue;
if (nrSlotsADay(null, dayCode, week, assignments, null) > getType().getMax())
return false;
}
} else {
if (nrSlotsADay(null, dayCode, null, assignments, null) > getType().getMax())
return false;
}
}
}
return true;
}
Aggregations