001 package net.sf.cpsolver.coursett.criteria;
002
003 import java.util.Collection;
004 import java.util.HashMap;
005 import java.util.HashSet;
006 import java.util.Map;
007 import java.util.Set;
008
009 import net.sf.cpsolver.coursett.constraint.FlexibleConstraint;
010 import net.sf.cpsolver.coursett.constraint.FlexibleConstraint.FlexibleConstraintType;
011 import net.sf.cpsolver.coursett.model.Lecture;
012 import net.sf.cpsolver.coursett.model.Placement;
013 import net.sf.cpsolver.coursett.model.TimetableModel;
014 import net.sf.cpsolver.ifs.solver.Solver;
015
016 /**
017 * The class encapsulates various flexible constraints concerning compact timetables of
018 * instructors.
019 *
020 * <br>
021 * @version CourseTT 1.2 (University Course Timetabling)<br>
022 * Copyright (C) 2012 Matej Lukac<br>
023 * <br>
024 * This library is free software; you can redistribute it and/or modify
025 * it under the terms of the GNU Lesser General Public License as
026 * published by the Free Software Foundation; either version 3 of the
027 * License, or (at your option) any later version. <br>
028 * <br>
029 * This library is distributed in the hope that it will be useful, but
030 * WITHOUT ANY WARRANTY; without even the implied warranty of
031 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
032 * Lesser General Public License for more details. <br>
033 * <br>
034 * You should have received a copy of the GNU Lesser General Public
035 * License along with this library; if not see
036 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
037 */
038 public class FlexibleConstraintCriterion extends TimetablingCriterion {
039
040 private boolean iDebug;
041
042 public FlexibleConstraintCriterion(){
043 iValueUpdateType = ValueUpdateType.NoUpdate;
044 }
045
046 @Override
047 public boolean init(Solver<Lecture, Placement> solver) {
048 super.init(solver);
049
050 iWeight = solver.getProperties().getPropertyDouble("FlexibleConstraint.Weight", 1.0d);
051 iDebug = solver.getProperties().getPropertyBoolean("FlexibleConstraint.Debug", true);
052 return true;
053 }
054
055 @Override
056 public String getPlacementSelectionWeightName() {
057 return "Placement.FlexibleConstrPreferenceWeight";
058 }
059
060 @Override
061 public void getInfo(Map<String, String> info) {
062 TimetableModel m = (TimetableModel)getModel();
063 if (m.getFlexibleConstraints().isEmpty()) return;
064
065 for (FlexibleConstraintType type: FlexibleConstraintType.values()) {
066 StringBuilder debug = null;
067 int violated = 0, constraints = 0;
068
069 for (FlexibleConstraint c : m.getFlexibleConstraints()) {
070 if (type.equals(c.getType())) {
071 constraints ++;
072 if (!c.isConsistent(null, null)) {
073 violated++;
074 if (iDebug) {
075 if (debug == null)
076 debug = new StringBuilder(c.getOwner());
077 else
078 debug.append("; " + c.getOwner());
079 }
080 }
081 }
082 }
083
084 if (constraints > 0) {
085 info.put(type.getName() + " Constraints", getPerc(violated, 0, constraints) + "% (" + violated + ")");
086 if (iDebug && violated > 0) info.put(type.getName() + " Violations", debug.toString());
087 }
088 }
089 }
090
091 @Override
092 public void getInfo(Map<String, String> info, Collection<Lecture> variables) {
093 for (FlexibleConstraintType type: FlexibleConstraintType.values()) {
094
095 Set<FlexibleConstraint> constraints = new HashSet<FlexibleConstraint>();
096 for (Lecture lecture : variables) {
097 for (FlexibleConstraint c : lecture.getFlexibleGroupConstraints()) {
098 if (type.equals(c.getType())) constraints.add(c);
099 }
100 }
101
102 if (!constraints.isEmpty()) {
103 int violated = 0;
104 StringBuilder debug = null;
105 for (FlexibleConstraint c : constraints) {
106 if (!c.isConsistent(null, null)) {
107 violated++;
108 if (iDebug) {
109 if (debug == null)
110 debug = new StringBuilder(c.getOwner());
111 else
112 debug.append("; " + c.getOwner());
113 }
114 }
115 }
116 info.put(type.getName() + " Constraints", getPerc(violated, 0, constraints.size()) + "% (" + violated + ")");
117 if (iDebug && violated > 0) info.put(type.getName() + " Violations", debug.toString());
118 }
119 }
120 }
121
122 @Override
123 public double getValue(Collection<Lecture> variables) {
124 Set<FlexibleConstraint> flexibleConstraints = new HashSet<FlexibleConstraint>();
125 for (Lecture lecture: variables){
126 flexibleConstraints.addAll(lecture.getFlexibleGroupConstraints());
127 }
128 int ret = 0;
129 for (FlexibleConstraint gc: flexibleConstraints){
130 ret += gc.getCurrentPreference(null, null);
131 }
132 return ret;
133 }
134
135 @Override
136 public double getValue(Placement value, Set<Placement> conflicts) {
137 HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
138 if (value != null) assignments.put(value.variable(), value);
139
140 double ret = 0.0;
141 for (FlexibleConstraint gc : value.variable().getFlexibleGroupConstraints())
142 ret += gc.getCurrentPreference(conflicts, assignments);
143 return ret;
144 }
145 }