
org.cpsolver.coursett.constraint.MaxWeeksFlexibleConstraint Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cpsolver Show documentation
Show all versions of cpsolver Show documentation
The constraint solver library contains a local search based framework that allows
modeling of a problem using constraint programming primitives (variables, values, constraints).
The newest version!
package org.cpsolver.coursett.constraint;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.cpsolver.coursett.criteria.FlexibleConstraintCriterion;
import org.cpsolver.coursett.model.Lecture;
import org.cpsolver.coursett.model.Placement;
import org.cpsolver.coursett.model.TimetableModel;
import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.criteria.Criterion;
import org.cpsolver.ifs.util.ToolBox;
/**
*
* The MaxWeeks constraint limits the number of weeks during which the given set of classes are taught.
* It has two parameters: a maximal number of weeks during which the given set of classes can be placed
* and a day code indicating what days of week are considered.
* Reference _MaxWeeks:3:6_ translates to a maximum number of 3 weeks, but only for classes that are placed on Fridays and Saturdays
* (64 for Monday, 32 for Tuesday, 16 for Wednesday, 8 for Thursday, 4 for Friday, 2 for Saturday, and 1 for Sunday).
* If the second parameter is zero, all days of week are considered.
*
* @author Tomas Muller
* @version CourseTT 1.3 (University Course Timetabling)
* Copyright (C) 2013 - 2014 Tomas Muller
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not see
* http://www.gnu.org/licenses/.
*/
public class MaxWeeksFlexibleConstraint extends FlexibleConstraint {
private int iMaxWeeks;
private int iDayCode;
public MaxWeeksFlexibleConstraint(Long id, String owner, String preference, String reference) {
super(id, owner, preference, reference);
Matcher matcher = Pattern.compile(FlexibleConstraintType.MAX_WEEKS.getPattern()).matcher(reference);
if (matcher.find()) {
iMaxWeeks = Integer.parseInt(matcher.group(2));
iDayCode = Integer.parseInt(matcher.group(3));
iConstraintType = FlexibleConstraintType.MAX_WEEKS;
}
}
public boolean isCorectDayOfWeek(Placement value) {
return value != null && value.getTimeLocation() != null && (iDayCode == 0 || (iDayCode & value.getTimeLocation().getDayCode()) != 0);
}
@Override
public double getNrViolations(Assignment assignment, Set conflicts, HashMap assignments) {
return ((MaxWeeksFlexibleConstraintContext)getContext(assignment)).nrViolations(assignments, conflicts);
}
@Override
public void computeConflicts(Assignment assignment, Placement value, Set conflicts) {
if (!isHard() || !isCorectDayOfWeek(value)) return;
MaxWeeksFlexibleConstraintContext context = (MaxWeeksFlexibleConstraintContext)getContext(assignment);
while (context.nrWeeks(value, conflicts) > iMaxWeeks) {
Set candidates = context.candidates(value, conflicts);
if (candidates == null) return;
for (Lecture candidate: candidates) {
Placement conflict = assignment.getValue(candidate);
if (conflict != null)
conflicts.add(conflict);
}
}
}
@Override
public boolean inConflict(Assignment assignment, Placement value) {
if (!isHard() || !isCorectDayOfWeek(value)) return false;
return ((MaxWeeksFlexibleConstraintContext)getContext(assignment)).nrWeeks(value, null) > iMaxWeeks;
}
@Override
public FlexibleConstraintContext createAssignmentContext(Assignment assignment) {
return new MaxWeeksFlexibleConstraintContext(assignment);
}
public class MaxWeeksFlexibleConstraintContext extends FlexibleConstraintContext {
private List iWeeks = null;
private Set iWeekAssignments[] = null;
@SuppressWarnings("unchecked")
public MaxWeeksFlexibleConstraintContext(Assignment assignment) {
super();
iWeeks = ((TimetableModel)getModel()).getWeeks();
iWeekAssignments = new Set[iWeeks.size()];
for (int i = 0; i < iWeekAssignments.length; i++)
iWeekAssignments[i] = new HashSet();
for (Lecture variable: variables()) {
Placement value = assignment.getValue(variable);
if (value != null && isCorectDayOfWeek(value)) {
for (int i = 0; i < iWeeks.size(); i++)
if (value.getTimeLocation().shareWeeks(iWeeks.get(i)))
iWeekAssignments[i].add(value.variable());
}
}
if (!isHard()) {
Criterion criterion = getModel().getCriterion(FlexibleConstraintCriterion.class);
if (criterion != null) {
double pref = nrViolations(null, null);
if (pref == 0)
iLastPreference = -Math.abs(iPreference);
else
iLastPreference = Math.abs(iPreference) * pref;
criterion.inc(assignment, iLastPreference);
}
}
}
@Override
public void assigned(Assignment assignment, Placement value) {
if (isCorectDayOfWeek(value)) {
for (int i = 0; i < iWeeks.size(); i++)
if (value.getTimeLocation().shareWeeks(iWeeks.get(i)))
iWeekAssignments[i].add(value.variable());
updateCriterion(assignment);
}
}
@Override
public void unassigned(Assignment assignment, Placement value) {
if (isCorectDayOfWeek(value)) {
for (int i = 0; i < iWeeks.size(); i++)
if (value.getTimeLocation().shareWeeks(iWeeks.get(i)))
iWeekAssignments[i].remove(value.variable());
updateCriterion(assignment);
}
}
public int nrWeeks(Placement value, Set conflicts) {
int ret = 0;
for (int i = 0; i < iWeeks.size(); i++) {
BitSet w = iWeeks.get(i);
int cnt = iWeekAssignments[i].size();
if (value != null) {
if (value.getTimeLocation().shareWeeks(w)) cnt ++;
if (iWeekAssignments[i].contains(value.variable())) cnt --;
}
if (conflicts != null) {
for (Placement conflict: conflicts) {
if (value != null && conflict.variable().equals(value.variable())) continue;
if (iWeekAssignments[i].contains(conflict.variable())) cnt --;
}
}
if (cnt > 0) ret++;
}
return ret;
}
public Set candidates(Placement value, Set conflicts) {
int bestCnt = 0;
List bestWeeks = new ArrayList();
for (int i = 0; i < iWeeks.size(); i++) {
BitSet w = iWeeks.get(i);
if (value.getTimeLocation().shareWeeks(w)) continue;
int cnt = iWeekAssignments[i].size();
if (iWeekAssignments[i].contains(value.variable())) cnt --;
for (Placement conflict: conflicts) {
if (conflict.variable().equals(value.variable())) continue;
if (iWeekAssignments[i].contains(conflict.variable())) cnt --;
}
if (cnt <= 0) continue;
if (bestWeeks.isEmpty() || bestCnt > cnt) {
bestWeeks.clear(); bestWeeks.add(i); bestCnt = cnt;
} else if (bestCnt == cnt) {
bestWeeks.add(i);
}
}
return bestWeeks.isEmpty() ? null : iWeekAssignments[ToolBox.random(bestWeeks)];
}
public int nrViolations(HashMap assignments, Set conflicts) {
int weeks = 0;
for (int i = 0; i < iWeeks.size(); i++) {
BitSet w = iWeeks.get(i);
int cnt = iWeekAssignments[i].size();
if (assignments != null) {
for (Map.Entry entry: assignments.entrySet()) {
if (isCorectDayOfWeek(entry.getValue()) && entry.getValue().getTimeLocation().shareWeeks(w)) cnt ++;
if (iWeekAssignments[i].contains(entry.getKey())) cnt --;
}
}
if (conflicts != null)
for (Placement conflict: conflicts) {
if (assignments != null && assignments.containsKey(conflict.variable())) continue;
if (iWeekAssignments[i].contains(conflict.variable())) cnt --;
}
if (cnt > 0) weeks ++;
}
return (weeks <= iMaxWeeks ? 0 : weeks - iMaxWeeks);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy