
org.cpsolver.instructor.constraints.SameLinkConstraint 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.instructor.constraints;
import java.util.HashSet;
import java.util.Set;
import org.cpsolver.coursett.Constants;
import org.cpsolver.ifs.assignment.Assignment;
import org.cpsolver.ifs.assignment.context.AssignmentConstraintContext;
import org.cpsolver.ifs.assignment.context.ConstraintWithContext;
import org.cpsolver.instructor.criteria.SameLink;
import org.cpsolver.instructor.model.Instructor;
import org.cpsolver.instructor.model.TeachingAssignment;
import org.cpsolver.instructor.model.TeachingRequest;
/**
* Same Link Constraint. Much like the {@link SameInstructorConstraint}, but it is possible to assign multiple instructors
* to the teaching requests of the same link. It is, however, prohibited (or discouraged) for an instructor to teach
* have teaching requests than the ones of the link. In prohibited / discouraged variant, each request must / should get
* a different instructor.
*
* @author Tomas Muller
* @version IFS 1.3 (Instructor Sectioning)
* Copyright (C) 2016 Tomas Muller
* [email protected]
* http://muller.unitime.org
*
* 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 SameLinkConstraint extends ConstraintWithContext {
private Long iId;
private String iName;
private int iPreference = 0;
private boolean iRequired = false, iProhibited = false;
/**
* Constructor
* @param id constraint id
* @param name link name
* @param preference constraint preference (R for required, etc.)
*/
public SameLinkConstraint(Long id, String name, String preference) {
iId = id;
iName = name;
iPreference = Constants.preference2preferenceLevel(preference);
if (Constants.sPreferenceRequired.equals(preference)) {
iRequired = true;
} else if (Constants.sPreferenceProhibited.equals(preference)) {
iProhibited = true;
}
}
/**
* Constraint id that was given in the constructor.
* @return constraint id
*/
public Long getConstraintId() { return iId; }
@Override
public String getName() { return iName; }
@Override
public String toString() { return "Same Link " + getName(); }
/**
* Is required?
* @return true if the constraint is required
*/
public boolean isRequired() { return iRequired; }
/**
* Is prohibited?
* @return true if the constraint is prohibited
*/
public boolean isProhibited() { return iProhibited; }
/**
* Constraint preference that was provided in the constructor
* @return constraint preference
*/
public int getPreference() { return iPreference; }
@Override
public boolean isHard() {
return isRequired() || isProhibited();
}
@Override
public void computeConflicts(Assignment assignment, TeachingAssignment value, Set conflicts) {
if (isHard()) {
Instructor.Context context = value.getInstructor().getContext(assignment);
for (TeachingAssignment ta : context.getAssignments()) {
if (ta.variable().equals(value.variable()) || conflicts.contains(ta))
continue;
if (isRequired() && !variables().contains(ta.variable()))
conflicts.add(ta);
if (isProhibited() && variables().contains(ta.variable()))
conflicts.add(ta);
}
}
}
/**
* Current constraint preference (if soft)
* @param assignment current assignment
* @param value proposed change
* @return change in the current preference value of this constraint
*/
public int getCurrentPreference(Assignment assignment, TeachingAssignment value) {
if (isHard()) return 0; // no preference
TeachingAssignment current = assignment.getValue(value.variable());
if (current != null && current.getInstructor().equals(value.getInstructor())) return 0;
int ret = 0;
if (getPreference() < 0) { // preferred
for (TeachingAssignment other : value.getInstructor().getContext(assignment).getAssignments()) {
if (!variables().equals(value.variable()) && !variables().contains(other.variable())) {
ret++;
}
}
if (current != null) {
for (TeachingAssignment other : current.getInstructor().getContext(assignment).getAssignments()) {
if (!variables().equals(value.variable()) && !variables().contains(other.variable())) {
ret--;
}
}
}
} else if (getPreference() > 0) {
for (TeachingAssignment other : value.getInstructor().getContext(assignment).getAssignments()) {
if (!variables().equals(value.variable()) && variables().contains(other.variable()))
ret++;
}
if (current != null) {
for (TeachingAssignment other : current.getInstructor().getContext(assignment).getAssignments()) {
if (!variables().equals(value.variable()) && variables().contains(other.variable())) {
ret--;
}
}
}
}
return ret;
}
/**
* Current constraint preference (if soft)
* @param assignment current assignment
* @return that is number of requests that are not of this link assigned to the instructors that have at least one request of this link if preferred;
* number of additional requests of this link given to the same instructor if discouraged
*/
public int getCurrentPreference(Assignment assignment) {
if (isHard()) return 0; // no preference
if (getPreference() < 0) { // preferred
int ret = 0;
Set checked = new HashSet();
for (TeachingRequest.Variable tr: variables()) {
TeachingAssignment ta = assignment.getValue(tr);
if (ta == null || !checked.add(ta.getInstructor())) continue;
Instructor.Context context = ta.getInstructor().getContext(assignment);
for (TeachingAssignment other : context.getAssignments()) {
if (!variables().contains(other.variable())) {
ret++;
}
}
}
return ret;
} else if (getPreference() > 0) {
int ret = 0;
Set checked = new HashSet();
for (TeachingRequest.Variable tr: variables()) {
TeachingAssignment ta = assignment.getValue(tr);
if (ta == null || !checked.add(ta.getInstructor())) continue;
Instructor.Context context = ta.getInstructor().getContext(assignment);
for (TeachingAssignment other : context.getAssignments()) {
if (!variables().equals(tr) && variables().contains(other.variable())) {
ret++;
}
}
}
return ret;
} else {
return 0;
}
}
@Override
public Context createAssignmentContext(Assignment assignment) {
return new Context(assignment);
}
/**
* Same Link Constraint Context. This context keeps the last preference value and updates the {@link SameLink} criterion.
*/
public class Context implements AssignmentConstraintContext {
private int iLastPreference = 0;
public Context(Assignment assignment) {
updateCriterion(assignment);
}
@Override
public void assigned(Assignment assignment, TeachingAssignment value) {
updateCriterion(assignment);
}
@Override
public void unassigned(Assignment assignment, TeachingAssignment value) {
updateCriterion(assignment);
}
/**
* Update the current preference value
* @param assignment current assignment
*/
private void updateCriterion(Assignment assignment) {
if (!isHard()) {
getModel().getCriterion(SameLink.class).inc(assignment, -iLastPreference);
iLastPreference = getCurrentPreference(assignment);
getModel().getCriterion(SameLink.class).inc(assignment, iLastPreference);
}
}
/**
* Current preference value (see {@link SameLinkConstraint#getCurrentPreference(Assignment)})
* @return current preference value
*/
public int getPreference() { return iLastPreference; }
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy