001 package net.sf.cpsolver.coursett.heuristics;
002
003 import java.util.HashMap;
004 import java.util.Iterator;
005 import java.util.List;
006 import java.util.Map;
007 import java.util.Set;
008
009 import net.sf.cpsolver.coursett.Constants;
010 import net.sf.cpsolver.coursett.constraint.InstructorConstraint;
011 import net.sf.cpsolver.coursett.model.Lecture;
012 import net.sf.cpsolver.coursett.model.Placement;
013 import net.sf.cpsolver.coursett.model.Student;
014 import net.sf.cpsolver.coursett.model.TimetableModel;
015 import net.sf.cpsolver.ifs.perturbations.DefaultPerturbationsCounter;
016 import net.sf.cpsolver.ifs.util.DataProperties;
017 import net.sf.cpsolver.ifs.util.DistanceMetric;
018
019 /**
020 * Perturbation penalty computation. <br>
021 * <br>
022 * In practise, the strategy for computing perturbations needs to be extended.
023 * For example, a change in time is usually much worse than a movement to a
024 * different classroom. The number of enrolled/involved students should also be
025 * taken into account. Another factor is whether the solution has already been
026 * published or not. <br>
027 * The priorities for evaluating perturbations are as follows. Before publishing
028 * timetable:
029 * <ul>
030 * <li>minimize number of classes with time changes,
031 * <li>minimize number of student conflicts,
032 * <li>optimize satisfaction of problem soft constraints.
033 * </ul>
034 * <br>
035 * After publishing the timetable (class time changes are not allowed):
036 * <ul>
037 * <li>minimize number of additional (new) student conflicts,
038 * <li>minimize number of students with time changes,
039 * <li>minimize number of classes with time changes,
040 * <li>optimize satisfaction of problem soft constraints.
041 * </ul>
042 * In both cases, the number of classes with room change is not significant at
043 * all. Before the timetable is published, minimizing the number of classes with
044 * time changes is the most important criteria for the MPP as long as it does
045 * not create too many additional student conflicts in the process. Therefore,
046 * as a compromise, the cost (in equivalent conflicts) of changing the time
047 * assigned to a class equals a number like 5% of the students enrolled in that
048 * class. Otherwise none of our other criteria would have any importance. <br>
049 * <br>
050 * Similar properties apply between other criteria as well. To fulfil all these
051 * needs we have crated a function (called perturbations penalty) which can be
052 * computed over a partial solution. This is a weighted sum of various
053 * perturbations criteria like the number of classes with time changes or the
054 * number of additional student conflicts. This perturbation penalty is added as
055 * an extra optimization criterion to the solution comparator and to value
056 * selection criterion, so we can also setup the weights between this
057 * perturbation penalty and other (initial) soft constraints. <br>
058 * <br>
059 * Parameters:
060 * <table border='1'>
061 * <tr>
062 * <th>Parameter</th>
063 * <th>Type</th>
064 * <th>Comment</th>
065 * </tr>
066 * <tr>
067 * <td>Perturbations.DifferentPlacement</td>
068 * <td>{@link Double}</td>
069 * <td>Different value than initial is assigned</td>
070 * </tr>
071 * <tr>
072 * <td>Perturbations.AffectedStudentWeight</td>
073 * <td>{@link Double}</td>
074 * <td>Number of students which are enrolled in a class which is placed to a
075 * different location than initial (a student can be included twice or more)</td>
076 * </tr>
077 * <tr>
078 * <td>Perturbations.AffectedInstructorWeight</td>
079 * <td>{@link Double}</td>
080 * <td>Number of instructors which are assigned to classes which are placed to
081 * different locations than initial (an instructor can be included twice or
082 * more)</td>
083 * </tr>
084 * <tr>
085 * <td>Perturbations.DifferentRoomWeight</td>
086 * <td>{@link Double}</td>
087 * <td>Number of classes which are placed to a different room than initial</td>
088 * </tr>
089 * <tr>
090 * <td>Perturbations.DifferentBuildingWeight</td>
091 * <td>{@link Double}</td>
092 * <td>Number of classes which are placed to a different building than initial</td>
093 * </tr>
094 * <tr>
095 * <td>Perturbations.DifferentTimeWeight</td>
096 * <td>{@link Double}</td>
097 * <td>Number of classes which are placed in a different time than initial</td>
098 * </tr>
099 * <tr>
100 * <td>Perturbations.DifferentDayWeight</td>
101 * <td>{@link Double}</td>
102 * <td>Number of classes which are placed in a different days than initial</td>
103 * </tr>
104 * <tr>
105 * <td>Perturbations.DifferentHourWeight</td>
106 * <td>{@link Double}</td>
107 * <td>Number of classes which are placed in a different hours than initial</td>
108 * </tr>
109 * <tr>
110 * <td>Perturbations.DeltaStudentConflictsWeight</td>
111 * <td>{@link Double}</td>
112 * <td>Difference of student conflicts of classes assigned to current placements
113 * instead of initial placements. It is a difference between number of students
114 * conflicts which are in the initial solution and the current one. Student
115 * conflicts created by classes without initial placement are not taken into
116 * account</td>
117 * </tr>
118 * <tr>
119 * <td>Perturbations.NewStudentConflictsWeight</td>
120 * <td>{@link Double}</td>
121 * <td>New created student conflicts -- particular students are taken into
122 * account. Student conflicts created by classes without initial placement are
123 * not taken into account</td>
124 * </tr>
125 * <tr>
126 * <td>Perturbations.TooFarForInstructorsWeight</td>
127 * <td>{@link Double}</td>
128 * <td>New placement of a class is too far from the intial placement
129 * (instructor-wise). It is computed only when the class has an instructor
130 * assigned, moreover:
131 * <ul>
132 * <li>0 < distance(currentPlacement,initialPlacement) <= 5 .. weight is taken
133 * once
134 * <li>5 < distance(currentPlacement,initialPlacement) <= 20 .. weight is taken
135 * twice
136 * <li>20 < distance(currentPlacement,initialPlacement) .. weight is taken ten
137 * times
138 * </ul>
139 * </td>
140 * </tr>
141 * <tr>
142 * <td>Perturbations.TooFarForStudentsWeight</td>
143 * <td>{@link Double}</td>
144 * <td>New placement of a class is too far from the intial placement
145 * (instructor-student). It is weighted by the number of students enrolled in
146 * the class when distance(currentPlacement,initialPlacement) > 67</td>
147 * </tr>
148 * <tr>
149 * <td>Perturbations.DeltaInstructorDistancePreferenceWeight</td>
150 * <td>{@link Double}</td>
151 * <td>Difference between number of instructor distance preferences of the
152 * initial (but maybe inconsistent) solution and the current solution.
153 * Instructor distance preferences of classes without initial placement are not
154 * taken into account</td>
155 * </tr>
156 * <tr>
157 * <td>Perturbations.DeltaRoomPreferenceWeight</td>
158 * <td>{@link Double}</td>
159 * <td>Difference between room preferences of the initial and the current
160 * solution. Room preferences of classes without initial placement are not taken
161 * into account</td>
162 * </tr>
163 * <tr>
164 * <td>Perturbations.DeltaTimePreferenceWeight</td>
165 * <td>{@link Double}</td>
166 * <td>Difference between time preferences of the initial and the current
167 * solution. Time preferences of classes without initial placement are not taken
168 * into account</td>
169 * </tr>
170 * <tr>
171 * <td>Perturbations.AffectedStudentByTimeWeight</td>
172 * <td>{@link Double}</td>
173 * <td>Number of students which are enrolled in a class which is placed to a
174 * different time than initial</td>
175 * </tr>
176 * <tr>
177 * <td>Perturbations.AffectedInstructorByTimeWeight</td>
178 * <td>{@link Double}</td>
179 * <td>Number of instructors which are assigned to classes which are placed to
180 * different time than initial</td>
181 * </tr>
182 * <tr>
183 * <td>Perturbations.AffectedStudentByRoomWeight</td>
184 * <td>{@link Double}</td>
185 * <td>Number of students which are enrolled in a class which is placed to a
186 * different room than initial</td>
187 * </tr>
188 * <tr>
189 * <td>Perturbations.AffectedInstructorByRoomWeight</td>
190 * <td>{@link Double}</td>
191 * <td>Number of instructors which are assigned to classes which are placed to
192 * different room than initial</td>
193 * </tr>
194 * <tr>
195 * <td>Perturbations.AffectedStudentByBldgWeight</td>
196 * <td>{@link Double}</td>
197 * <td>Number of students which are enrolled in a class which is placed to a
198 * different building than initial</td>
199 * </tr>
200 * <tr>
201 * <td>Perturbations.AffectedInstructorByBldgWeight</td>
202 * <td>{@link Double}</td>
203 * <td>Number of instructors which are assigned to classes which are placed to
204 * different building than initial</td>
205 * </tr>
206 * </table>
207 *
208 * @version CourseTT 1.2 (University Course Timetabling)<br>
209 * Copyright (C) 2006 - 2010 Tomas Muller<br>
210 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
211 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
212 * <br>
213 * This library is free software; you can redistribute it and/or modify
214 * it under the terms of the GNU Lesser General Public License as
215 * published by the Free Software Foundation; either version 3 of the
216 * License, or (at your option) any later version. <br>
217 * <br>
218 * This library is distributed in the hope that it will be useful, but
219 * WITHOUT ANY WARRANTY; without even the implied warranty of
220 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
221 * Lesser General Public License for more details. <br>
222 * <br>
223 * You should have received a copy of the GNU Lesser General Public
224 * License along with this library; if not see
225 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
226 */
227
228 public class UniversalPerturbationsCounter extends DefaultPerturbationsCounter<Lecture, Placement> {
229 private double iDifferentPlacement = 1.0;
230 private double iAffectedStudentWeight = 0.0;
231 private double iAffectedInstructorWeight = 0.0;
232 private double iAffectedStudentByTimeWeight = 0.0;
233 private double iAffectedInstructorByTimeWeight = 0.0;
234 private double iAffectedStudentByRoomWeight = 0.0;
235 private double iAffectedInstructorByRoomWeight = 0.0;
236 private double iAffectedStudentByBldgWeight = 0.0;
237 private double iAffectedInstructorByBldgWeight = 0.0;
238 private double iDifferentRoomWeight = 0.0;
239 private double iDifferentBuildingWeight = 0.0;
240 private double iDifferentTimeWeight = 0.0;
241 private double iDifferentDayWeight = 0.0;
242 private double iDifferentHourWeight = 0.0;
243 private double iNewStudentConflictsWeight = 0.0;
244 private double iDeltaStudentConflictsWeight = 0.0;
245 private double iTooFarForInstructorsWeight = 0.0;
246 private double iTooFarForStudentsWeight = 0.0;
247 private double iDeltaInstructorDistancePreferenceWeight = 0.0;
248 private double iDeltaRoomPreferenceWeight = 0.0;
249 private double iDeltaTimePreferenceWeight = 0.0;
250 private boolean iMPP = false;
251 private DistanceMetric iDistanceMetric = null;
252
253 public UniversalPerturbationsCounter(DataProperties properties) {
254 super(properties);
255 iMPP = properties.getPropertyBoolean("General.MPP", false);
256 iDifferentPlacement = properties.getPropertyDouble("Perturbations.DifferentPlacement", iDifferentPlacement);
257 iAffectedStudentWeight = properties.getPropertyDouble("Perturbations.AffectedStudentWeight",
258 iAffectedStudentWeight);
259 iAffectedInstructorWeight = properties.getPropertyDouble("Perturbations.AffectedInstructorWeight",
260 iAffectedInstructorWeight);
261 iAffectedStudentByTimeWeight = properties.getPropertyDouble("Perturbations.AffectedStudentByTimeWeight",
262 iAffectedStudentByTimeWeight);
263 iAffectedInstructorByTimeWeight = properties.getPropertyDouble("Perturbations.AffectedInstructorByTimeWeight",
264 iAffectedInstructorByTimeWeight);
265 iAffectedStudentByRoomWeight = properties.getPropertyDouble("Perturbations.AffectedStudentByRoomWeight",
266 iAffectedStudentByRoomWeight);
267 iAffectedInstructorByRoomWeight = properties.getPropertyDouble("Perturbations.AffectedInstructorByRoomWeight",
268 iAffectedInstructorByRoomWeight);
269 iAffectedStudentByBldgWeight = properties.getPropertyDouble("Perturbations.AffectedStudentByBldgWeight",
270 iAffectedStudentByBldgWeight);
271 iAffectedInstructorByBldgWeight = properties.getPropertyDouble("Perturbations.AffectedInstructorByBldgWeight",
272 iAffectedInstructorByBldgWeight);
273 iDifferentRoomWeight = properties.getPropertyDouble("Perturbations.DifferentRoomWeight", iDifferentRoomWeight);
274 iDifferentBuildingWeight = properties.getPropertyDouble("Perturbations.DifferentBuildingWeight",
275 iDifferentBuildingWeight);
276 iDifferentTimeWeight = properties.getPropertyDouble("Perturbations.DifferentTimeWeight", iDifferentTimeWeight);
277 iDifferentDayWeight = properties.getPropertyDouble("Perturbations.DifferentDayWeight", iDifferentDayWeight);
278 iDifferentHourWeight = properties.getPropertyDouble("Perturbations.DifferentHourWeight", iDifferentHourWeight);
279 iDeltaStudentConflictsWeight = properties.getPropertyDouble("Perturbations.DeltaStudentConflictsWeight",
280 iDeltaStudentConflictsWeight);
281 iNewStudentConflictsWeight = properties.getPropertyDouble("Perturbations.NewStudentConflictsWeight",
282 iNewStudentConflictsWeight);
283 iTooFarForInstructorsWeight = properties.getPropertyDouble("Perturbations.TooFarForInstructorsWeight",
284 iTooFarForInstructorsWeight);
285 iTooFarForStudentsWeight = properties.getPropertyDouble("Perturbations.TooFarForStudentsWeight",
286 iTooFarForStudentsWeight);
287 iDeltaInstructorDistancePreferenceWeight = properties.getPropertyDouble(
288 "Perturbations.DeltaInstructorDistancePreferenceWeight", iDeltaInstructorDistancePreferenceWeight);
289 iDeltaRoomPreferenceWeight = properties.getPropertyDouble("Perturbations.DeltaRoomPreferenceWeight",
290 iDeltaRoomPreferenceWeight);
291 iDeltaTimePreferenceWeight = properties.getPropertyDouble("Perturbations.DeltaTimePreferenceWeight",
292 iDeltaTimePreferenceWeight);
293 iDistanceMetric = new DistanceMetric(properties);
294 }
295
296 @Override
297 protected double getPenalty(Placement assignedPlacement, Placement initialPlacement) {
298 // assigned and initial value of the same lecture
299 // assigned might be null
300 Lecture lecture = initialPlacement.variable();
301 double penalty = 0.0;
302 if (iDifferentPlacement != 0.0)
303 penalty += iDifferentPlacement;
304 if (iAffectedStudentWeight != 0.0)
305 penalty += iAffectedStudentWeight * lecture.classLimit();
306 if (iAffectedInstructorWeight != 0.0)
307 penalty += iAffectedInstructorWeight * lecture.getInstructorConstraints().size();
308 if (assignedPlacement != null) {
309 if ((iDifferentRoomWeight != 0.0 || iAffectedInstructorByRoomWeight != 0.0 || iAffectedStudentByRoomWeight != 0.0)) {
310 int nrDiff = initialPlacement.nrDifferentRooms(assignedPlacement);
311 penalty += nrDiff * iDifferentRoomWeight;
312 penalty += nrDiff * iAffectedInstructorByRoomWeight * lecture.getInstructorConstraints().size();
313 penalty += nrDiff * iAffectedStudentByRoomWeight * lecture.classLimit();
314 }
315 if ((iDifferentBuildingWeight != 0.0 || iAffectedInstructorByBldgWeight != 0.0 || iAffectedStudentByBldgWeight != 0.0)) {
316 int nrDiff = initialPlacement.nrDifferentBuildings(assignedPlacement);
317 penalty += nrDiff * iDifferentBuildingWeight;
318 penalty += nrDiff * iAffectedInstructorByBldgWeight * lecture.getInstructorConstraints().size();
319 penalty += nrDiff * iAffectedStudentByBldgWeight * lecture.classLimit();
320 }
321 if ((iDifferentTimeWeight != 0.0 || iAffectedInstructorByTimeWeight != 0.0 || iAffectedStudentByTimeWeight != 0.0)
322 && !initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
323 penalty += iDifferentTimeWeight;
324 penalty += iAffectedInstructorByTimeWeight * lecture.getInstructorConstraints().size();
325 penalty += iAffectedStudentByTimeWeight * lecture.classLimit();
326 }
327 if (iDifferentDayWeight != 0.0
328 && initialPlacement.getTimeLocation().getDayCode() != assignedPlacement.getTimeLocation()
329 .getDayCode())
330 penalty += iDifferentDayWeight;
331 if (iDifferentHourWeight != 0.0
332 && initialPlacement.getTimeLocation().getStartSlot() != assignedPlacement.getTimeLocation()
333 .getStartSlot())
334 penalty += iDifferentHourWeight;
335 if ((iTooFarForInstructorsWeight != 0.0 || iTooFarForStudentsWeight != 0.0)
336 && !initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
337 double distance = Placement.getDistanceInMeters(iDistanceMetric, initialPlacement, assignedPlacement);
338 if (!lecture.getInstructorConstraints().isEmpty() && iTooFarForInstructorsWeight != 0.0) {
339 if (distance > iDistanceMetric.getInstructorNoPreferenceLimit() && distance <= iDistanceMetric.getInstructorDiscouragedLimit()) {
340 penalty += Constants.sPreferenceLevelDiscouraged * iTooFarForInstructorsWeight
341 * lecture.getInstructorConstraints().size();
342 } else if (distance > iDistanceMetric.getInstructorDiscouragedLimit() && distance <= iDistanceMetric.getInstructorProhibitedLimit()) {
343 penalty += Constants.sPreferenceLevelStronglyDiscouraged * iTooFarForInstructorsWeight
344 * lecture.getInstructorConstraints().size();
345 } else if (distance > iDistanceMetric.getInstructorProhibitedLimit()) {
346 penalty += Constants.sPreferenceLevelProhibited * iTooFarForInstructorsWeight
347 * lecture.getInstructorConstraints().size();
348 }
349 }
350 if (iTooFarForStudentsWeight != 0.0
351 && distance > iDistanceMetric.minutes2meters(10))
352 penalty += iTooFarForStudentsWeight * lecture.classLimit();
353 }
354 if (iDeltaStudentConflictsWeight != 0.0) {
355 int newStudentConflicts = lecture.countStudentConflicts(assignedPlacement);
356 int oldStudentConflicts = lecture.countInitialStudentConflicts();
357 penalty += iDeltaStudentConflictsWeight * (newStudentConflicts - oldStudentConflicts);
358 }
359 if (iNewStudentConflictsWeight != 0.0) {
360 Set<Student> newStudentConflicts = lecture.conflictStudents(assignedPlacement);
361 Set<Student> initialStudentConflicts = lecture.initialStudentConflicts();
362 for (Iterator<Student> i = newStudentConflicts.iterator(); i.hasNext();)
363 if (!initialStudentConflicts.contains(i.next()))
364 penalty += iNewStudentConflictsWeight;
365 }
366 if (iDeltaTimePreferenceWeight != 0.0) {
367 penalty += iDeltaTimePreferenceWeight
368 * (assignedPlacement.getTimeLocation().getNormalizedPreference() - initialPlacement
369 .getTimeLocation().getNormalizedPreference());
370 }
371 if (iDeltaRoomPreferenceWeight != 0.0) {
372 penalty += iDeltaRoomPreferenceWeight
373 * (assignedPlacement.sumRoomPreference() - initialPlacement.sumRoomPreference());
374 }
375 if (iDeltaInstructorDistancePreferenceWeight != 0.0) {
376 for (InstructorConstraint ic : lecture.getInstructorConstraints()) {
377 for (Lecture lect : ic.variables()) {
378 if (lect.equals(lecture))
379 continue;
380 int initialPreference = (lect.getInitialAssignment() == null ? Constants.sPreferenceLevelNeutral
381 : ic.getDistancePreference(initialPlacement, lect.getInitialAssignment()));
382 int assignedPreference = (lect.getAssignment() == null ? Constants.sPreferenceLevelNeutral : ic
383 .getDistancePreference(assignedPlacement, lect.getAssignment()));
384 penalty += iDeltaInstructorDistancePreferenceWeight * (assignedPreference - initialPreference);
385 }
386 }
387 }
388 }
389 return penalty;
390 }
391
392 public void getInfo(Map<String, String> info, TimetableModel model) {
393 getInfo(info, model, null);
394 }
395
396 public void getInfo(Map<String, String> info, TimetableModel model, List<Lecture> variables) {
397 if (variables == null)
398 super.getInfo(info, model);
399 else
400 super.getInfo(info, model, variables);
401 if (!iMPP)
402 return;
403 int perts = 0;
404 long affectedStudents = 0;
405 int affectedInstructors = 0;
406 long affectedStudentsByTime = 0;
407 int affectedInstructorsByTime = 0;
408 long affectedStudentsByRoom = 0;
409 int affectedInstructorsByRoom = 0;
410 long affectedStudentsByBldg = 0;
411 int affectedInstructorsByBldg = 0;
412 int differentRoom = 0;
413 int differentBuilding = 0;
414 int differentTime = 0;
415 int differentDay = 0;
416 int differentHour = 0;
417 int tooFarForInstructors = 0;
418 int tooFarForStudents = 0;
419 int deltaStudentConflicts = 0;
420 int newStudentConflicts = 0;
421 double deltaTimePreferences = 0;
422 int deltaRoomPreferences = 0;
423 int deltaInstructorDistancePreferences = 0;
424 for (Lecture lecture : (variables == null ? model.perturbVariables() : model.perturbVariables(variables))) {
425 if (lecture.getAssignment() == null || lecture.getInitialAssignment() == null
426 || lecture.getAssignment().equals(lecture.getInitialAssignment()))
427 continue;
428 perts++;
429 Placement assignedPlacement = lecture.getAssignment();
430 Placement initialPlacement = lecture.getInitialAssignment();
431 affectedStudents += lecture.classLimit();
432 affectedInstructors += lecture.getInstructorConstraints().size();
433
434 int nrDiff = initialPlacement.nrDifferentRooms(assignedPlacement);
435 differentRoom += nrDiff;
436 affectedInstructorsByRoom += nrDiff * lecture.getInstructorConstraints().size();
437 affectedStudentsByRoom += nrDiff * lecture.classLimit();
438
439 nrDiff = initialPlacement.nrDifferentBuildings(assignedPlacement);
440 differentBuilding += nrDiff;
441 affectedInstructorsByBldg += nrDiff * lecture.getInstructorConstraints().size();
442 affectedStudentsByBldg += nrDiff * lecture.classLimit();
443
444 deltaRoomPreferences += assignedPlacement.sumRoomPreference() - initialPlacement.sumRoomPreference();
445
446 if (!initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
447 differentTime++;
448 affectedInstructorsByTime += lecture.getInstructorConstraints().size();
449 affectedStudentsByTime += lecture.classLimit();
450 }
451 if (initialPlacement.getTimeLocation().getDayCode() != assignedPlacement.getTimeLocation().getDayCode())
452 differentDay++;
453 if (initialPlacement.getTimeLocation().getStartSlot() != assignedPlacement.getTimeLocation().getStartSlot())
454 differentHour++;
455 if (!initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
456 double distance = Placement.getDistanceInMeters(iDistanceMetric, initialPlacement, assignedPlacement);
457 if (!lecture.getInstructorConstraints().isEmpty()) {
458 if (distance > iDistanceMetric.getInstructorNoPreferenceLimit() && distance <= iDistanceMetric.getInstructorDiscouragedLimit()) {
459 tooFarForInstructors += Constants.sPreferenceLevelDiscouraged
460 * lecture.getInstructorConstraints().size();
461 } else if (distance > iDistanceMetric.getInstructorDiscouragedLimit() && distance <= iDistanceMetric.getInstructorProhibitedLimit()) {
462 tooFarForInstructors += Constants.sPreferenceLevelStronglyDiscouraged
463 * lecture.getInstructorConstraints().size();
464 } else if (distance > iDistanceMetric.getInstructorProhibitedLimit()) {
465 tooFarForInstructors += Constants.sPreferenceLevelProhibited
466 * lecture.getInstructorConstraints().size();
467 }
468 }
469 if (distance > iDistanceMetric.minutes2meters(10))
470 tooFarForStudents += lecture.classLimit();
471 }
472 deltaStudentConflicts += lecture.countStudentConflicts(assignedPlacement)
473 - lecture.countInitialStudentConflicts();
474 Set<Student> newStudentConflictsSet = lecture.conflictStudents(assignedPlacement);
475 Set<Student> initialStudentConflicts = lecture.initialStudentConflicts();
476 for (Iterator<Student> e1 = newStudentConflictsSet.iterator(); e1.hasNext();)
477 if (!initialStudentConflicts.contains(e1.next()))
478 newStudentConflicts++;
479 deltaTimePreferences += assignedPlacement.getTimeLocation().getNormalizedPreference()
480 - initialPlacement.getTimeLocation().getNormalizedPreference();
481 for (InstructorConstraint ic : lecture.getInstructorConstraints()) {
482 for (Lecture lect : ic.variables()) {
483 if (lect.equals(lecture))
484 continue;
485 int initialPreference = (lect.getInitialAssignment() == null ? Constants.sPreferenceLevelNeutral
486 : ic.getDistancePreference(initialPlacement, lect.getInitialAssignment()));
487 int assignedPreference = (lect.getAssignment() == null ? Constants.sPreferenceLevelNeutral : ic
488 .getDistancePreference(assignedPlacement, lect.getAssignment()));
489 deltaInstructorDistancePreferences += assignedPreference - initialPreference;
490 }
491 }
492 }
493 if (perts != 0)
494 info.put("Perturbations: Different placement", String.valueOf(perts) + " (weighted "
495 + sDoubleFormat.format(iDifferentPlacement * perts) + ")");
496 if (affectedStudents != 0)
497 info.put("Perturbations: Number of affected students", String.valueOf(affectedStudents) + " (weighted "
498 + sDoubleFormat.format(iAffectedStudentWeight * affectedStudents) + ")");
499 if (affectedInstructors != 0)
500 info.put("Perturbations: Number of affected instructors", String.valueOf(affectedInstructors)
501 + " (weighted " + sDoubleFormat.format(iAffectedInstructorWeight * affectedInstructors) + ")");
502 if (affectedStudentsByTime != 0)
503 info
504 .put("Perturbations: Number of affected students [time]", String.valueOf(affectedStudentsByTime)
505 + " (weighted "
506 + sDoubleFormat.format(iAffectedStudentByTimeWeight * affectedStudentsByTime) + ")");
507 if (affectedInstructorsByTime != 0)
508 info.put("Perturbations: Number of affected instructors [time]", String.valueOf(affectedInstructorsByTime)
509 + " (weighted " + sDoubleFormat.format(iAffectedInstructorByTimeWeight * affectedInstructorsByTime)
510 + ")");
511 if (affectedStudentsByRoom != 0)
512 info
513 .put("Perturbations: Number of affected students [room]", String.valueOf(affectedStudentsByRoom)
514 + " (weighted "
515 + sDoubleFormat.format(iAffectedStudentByRoomWeight * affectedStudentsByRoom) + ")");
516 if (affectedInstructorsByRoom != 0)
517 info.put("Perturbations: Number of affected instructors [room]", String.valueOf(affectedInstructorsByRoom)
518 + " (weighted " + sDoubleFormat.format(iAffectedInstructorByRoomWeight * affectedInstructorsByRoom)
519 + ")");
520 if (affectedStudentsByBldg != 0)
521 info
522 .put("Perturbations: Number of affected students [bldg]", String.valueOf(affectedStudentsByBldg)
523 + " (weighted "
524 + sDoubleFormat.format(iAffectedStudentByBldgWeight * affectedStudentsByBldg) + ")");
525 if (affectedInstructorsByBldg != 0)
526 info.put("Perturbations: Number of affected instructors [bldg]", String.valueOf(affectedInstructorsByBldg)
527 + " (weighted " + sDoubleFormat.format(iAffectedInstructorByBldgWeight * affectedInstructorsByBldg)
528 + ")");
529 if (differentRoom != 0)
530 info.put("Perturbations: Different room", String.valueOf(differentRoom) + " (weighted "
531 + sDoubleFormat.format(iDifferentRoomWeight * differentRoom) + ")");
532 if (differentBuilding != 0)
533 info.put("Perturbations: Different building", String.valueOf(differentBuilding) + " (weighted "
534 + sDoubleFormat.format(iDifferentBuildingWeight * differentBuilding) + ")");
535 if (differentTime != 0)
536 info.put("Perturbations: Different time", String.valueOf(differentTime) + " (weighted "
537 + sDoubleFormat.format(iDifferentTimeWeight * differentTime) + ")");
538 if (differentDay != 0)
539 info.put("Perturbations: Different day", String.valueOf(differentDay) + " (weighted "
540 + sDoubleFormat.format(iDifferentDayWeight * differentDay) + ")");
541 if (differentHour != 0)
542 info.put("Perturbations: Different hour", String.valueOf(differentHour) + " (weighted "
543 + sDoubleFormat.format(iDifferentHourWeight * differentHour) + ")");
544 if (tooFarForInstructors != 0)
545 info.put("Perturbations: New placement too far from initial [instructors]", String
546 .valueOf(tooFarForInstructors)
547 + " (weighted " + sDoubleFormat.format(iTooFarForInstructorsWeight * tooFarForInstructors) + ")");
548 if (tooFarForStudents != 0)
549 info.put("Perturbations: New placement too far from initial [students]", String.valueOf(tooFarForStudents)
550 + " (weighted " + sDoubleFormat.format(iTooFarForStudentsWeight * tooFarForStudents) + ")");
551 if (deltaStudentConflicts != 0)
552 info.put("Perturbations: Delta student conflicts", String.valueOf(deltaStudentConflicts) + " (weighted "
553 + sDoubleFormat.format(iDeltaStudentConflictsWeight * deltaStudentConflicts) + ")");
554 if (newStudentConflicts != 0)
555 info.put("Perturbations: New student conflicts", String.valueOf(newStudentConflicts) + " (weighted "
556 + sDoubleFormat.format(iNewStudentConflictsWeight * newStudentConflicts) + ")");
557 if (deltaTimePreferences != 0)
558 info.put("Perturbations: Delta time preferences", String.valueOf(deltaTimePreferences) + " (weighted "
559 + sDoubleFormat.format(iDeltaTimePreferenceWeight * deltaTimePreferences) + ")");
560 if (deltaRoomPreferences != 0)
561 info.put("Perturbations: Delta room preferences", String.valueOf(deltaRoomPreferences) + " (weighted "
562 + sDoubleFormat.format(iDeltaRoomPreferenceWeight * deltaRoomPreferences) + ")");
563 if (deltaInstructorDistancePreferences != 0)
564 info.put("Perturbations: Delta instructor distance preferences", String
565 .valueOf(deltaInstructorDistancePreferences)
566 + " (weighted "
567 + sDoubleFormat.format(iDeltaInstructorDistancePreferenceWeight
568 * deltaInstructorDistancePreferences) + ")");
569 }
570
571 public Map<String, Double> getCompactInfo(TimetableModel model, boolean includeZero, boolean weighted) {
572 Map<String, Double> info = new HashMap<String, Double>();
573 if (!iMPP)
574 return info;
575 int perts = 0;
576 long affectedStudents = 0;
577 int affectedInstructors = 0;
578 long affectedStudentsByTime = 0;
579 int affectedInstructorsByTime = 0;
580 long affectedStudentsByRoom = 0;
581 int affectedInstructorsByRoom = 0;
582 long affectedStudentsByBldg = 0;
583 int affectedInstructorsByBldg = 0;
584 int differentRoom = 0;
585 int differentBuilding = 0;
586 int differentTime = 0;
587 int differentDay = 0;
588 int differentHour = 0;
589 int tooFarForInstructors = 0;
590 int tooFarForStudents = 0;
591 int deltaStudentConflicts = 0;
592 int newStudentConflicts = 0;
593 double deltaTimePreferences = 0;
594 int deltaRoomPreferences = 0;
595 int deltaInstructorDistancePreferences = 0;
596 for (Lecture lecture : model.perturbVariables()) {
597 if (lecture.getAssignment() == null || lecture.getInitialAssignment() == null
598 || lecture.getAssignment().equals(lecture.getInitialAssignment()))
599 continue;
600 perts++;
601 Placement assignedPlacement = lecture.getAssignment();
602 Placement initialPlacement = lecture.getInitialAssignment();
603 affectedStudents += lecture.classLimit();
604 affectedInstructors += lecture.getInstructorConstraints().size();
605
606 int nrDiff = initialPlacement.nrDifferentRooms(assignedPlacement);
607 differentRoom += nrDiff;
608 affectedInstructorsByRoom += nrDiff * lecture.getInstructorConstraints().size();
609 affectedStudentsByRoom += nrDiff * lecture.classLimit();
610
611 nrDiff = initialPlacement.nrDifferentBuildings(initialPlacement);
612 differentBuilding += nrDiff;
613 affectedInstructorsByBldg += nrDiff * lecture.getInstructorConstraints().size();
614 affectedStudentsByBldg += nrDiff * lecture.classLimit();
615
616 deltaRoomPreferences += assignedPlacement.sumRoomPreference() - initialPlacement.sumRoomPreference();
617
618 if (!initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
619 differentTime++;
620 affectedInstructorsByTime += lecture.getInstructorConstraints().size();
621 affectedStudentsByTime += lecture.classLimit();
622 }
623 if (initialPlacement.getTimeLocation().getDayCode() != assignedPlacement.getTimeLocation().getDayCode())
624 differentDay++;
625 if (initialPlacement.getTimeLocation().getStartSlot() != assignedPlacement.getTimeLocation().getStartSlot())
626 differentHour++;
627 if (!initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation())) {
628 double distance = Placement.getDistanceInMeters(iDistanceMetric, initialPlacement, assignedPlacement);
629 if (!lecture.getInstructorConstraints().isEmpty()) {
630 if (distance > iDistanceMetric.getInstructorNoPreferenceLimit() && distance <= iDistanceMetric.getInstructorDiscouragedLimit()) {
631 tooFarForInstructors += Constants.sPreferenceLevelDiscouraged;
632 } else if (distance > iDistanceMetric.getInstructorDiscouragedLimit() && distance <= iDistanceMetric.getInstructorProhibitedLimit()) {
633 tooFarForInstructors += Constants.sPreferenceLevelStronglyDiscouraged;
634 } else if (distance > iDistanceMetric.getInstructorProhibitedLimit()) {
635 tooFarForInstructors += Constants.sPreferenceLevelProhibited;
636 }
637 }
638 if (distance > iDistanceMetric.minutes2meters(10))
639 tooFarForStudents += lecture.classLimit();
640 }
641 deltaStudentConflicts += lecture.countStudentConflicts(assignedPlacement)
642 - lecture.countInitialStudentConflicts();
643 Set<Student> newStudentConflictsSet = lecture.conflictStudents(assignedPlacement);
644 Set<Student> initialStudentConflicts = lecture.initialStudentConflicts();
645 for (Iterator<Student> e1 = newStudentConflictsSet.iterator(); e1.hasNext();)
646 if (!initialStudentConflicts.contains(e1.next()))
647 newStudentConflicts++;
648 deltaTimePreferences += assignedPlacement.getTimeLocation().getNormalizedPreference()
649 - initialPlacement.getTimeLocation().getNormalizedPreference();
650 for (InstructorConstraint ic : lecture.getInstructorConstraints()) {
651 if (ic != null)
652 for (Lecture lect : ic.variables()) {
653 if (lect.equals(lecture))
654 continue;
655 int initialPreference = (lect.getInitialAssignment() == null ? Constants.sPreferenceLevelNeutral
656 : ic.getDistancePreference(initialPlacement, lect.getInitialAssignment()));
657 int assignedPreference = (lect.getAssignment() == null ? Constants.sPreferenceLevelNeutral : ic
658 .getDistancePreference(assignedPlacement, lect.getAssignment()));
659 deltaInstructorDistancePreferences += assignedPreference - initialPreference;
660 }
661 }
662 }
663 if (includeZero || iDifferentPlacement != 0.0)
664 info.put("Different placement", new Double(weighted ? iDifferentPlacement * perts : perts));
665 if (includeZero || iAffectedStudentWeight != 0.0)
666 info.put("Affected students", new Double(weighted ? iAffectedStudentWeight * affectedStudents
667 : affectedStudents));
668 if (includeZero || iAffectedInstructorWeight != 0.0)
669 info.put("Affected instructors", new Double(weighted ? iAffectedInstructorWeight * affectedInstructors
670 : affectedInstructors));
671 if (includeZero || iAffectedStudentByTimeWeight != 0.0)
672 info.put("Affected students [time]", new Double(weighted ? iAffectedStudentByTimeWeight
673 * affectedStudentsByTime : affectedStudentsByTime));
674 if (includeZero || iAffectedInstructorByTimeWeight != 0.0)
675 info.put("Affected instructors [time]", new Double(weighted ? iAffectedInstructorByTimeWeight
676 * affectedInstructorsByTime : affectedInstructorsByTime));
677 if (includeZero || iAffectedStudentByRoomWeight != 0.0)
678 info.put("Affected students [room]", new Double(weighted ? iAffectedStudentByRoomWeight
679 * affectedStudentsByRoom : affectedStudentsByRoom));
680 if (includeZero || iAffectedInstructorByRoomWeight != 0.0)
681 info.put("Affected instructors [room]", new Double(weighted ? iAffectedInstructorByRoomWeight
682 * affectedInstructorsByRoom : affectedInstructorsByRoom));
683 if (includeZero || iAffectedStudentByBldgWeight != 0.0)
684 info.put("Affected students [bldg]", new Double(weighted ? iAffectedStudentByBldgWeight
685 * affectedStudentsByBldg : affectedStudentsByBldg));
686 if (includeZero || iAffectedInstructorByBldgWeight != 0.0)
687 info.put("Affected instructors [bldg]", new Double(weighted ? iAffectedInstructorByBldgWeight
688 * affectedInstructorsByBldg : affectedInstructorsByBldg));
689 if (includeZero || iDifferentRoomWeight != 0.0)
690 info.put("Different room", new Double(weighted ? iDifferentRoomWeight * differentRoom : differentRoom));
691 if (includeZero || iDifferentBuildingWeight != 0.0)
692 info.put("Different building", new Double(weighted ? iDifferentBuildingWeight * differentBuilding
693 : differentBuilding));
694 if (includeZero || iDifferentTimeWeight != 0.0)
695 info.put("Different time", new Double(weighted ? iDifferentTimeWeight * differentTime : differentTime));
696 if (includeZero || iDifferentDayWeight != 0.0)
697 info.put("Different day", new Double(weighted ? iDifferentDayWeight * differentDay : differentDay));
698 if (includeZero || iDifferentHourWeight != 0.0)
699 info.put("Different hour", new Double(weighted ? iDifferentHourWeight * differentHour : differentHour));
700 if (includeZero || iTooFarForInstructorsWeight != 0.0)
701 info.put("New placement too far for initial [instructors]", new Double(
702 weighted ? iTooFarForInstructorsWeight * tooFarForInstructors : tooFarForInstructors));
703 if (includeZero || iTooFarForStudentsWeight != 0.0)
704 info.put("New placement too far for initial [students]", new Double(weighted ? iTooFarForStudentsWeight
705 * tooFarForStudents : tooFarForStudents));
706 if (includeZero || iDeltaStudentConflictsWeight != 0.0)
707 info.put("Delta student conflicts", new Double(weighted ? iDeltaStudentConflictsWeight
708 * deltaStudentConflicts : deltaStudentConflicts));
709 if (includeZero || iNewStudentConflictsWeight != 0.0)
710 info.put("New student conflicts", new Double(weighted ? iNewStudentConflictsWeight * newStudentConflicts
711 : newStudentConflicts));
712 if (includeZero || iDeltaTimePreferenceWeight != 0.0)
713 info.put("Delta time preferences", new Double(weighted ? iDeltaTimePreferenceWeight * deltaTimePreferences
714 : deltaTimePreferences));
715 if (includeZero || iDeltaRoomPreferenceWeight != 0.0)
716 info.put("Delta room preferences", new Double(weighted ? iDeltaRoomPreferenceWeight * deltaRoomPreferences
717 : deltaRoomPreferences));
718 if (includeZero || iDeltaInstructorDistancePreferenceWeight != 0.0)
719 info.put("Delta instructor distance preferences", new Double(
720 weighted ? iDeltaInstructorDistancePreferenceWeight * deltaInstructorDistancePreferences
721 : deltaInstructorDistancePreferences));
722 return info;
723 }
724
725 public Map<String, Double> getCompactInfo(TimetableModel model, Placement assignedPlacement, boolean includeZero,
726 boolean weighted) {
727 Map<String, Double> info = new HashMap<String, Double>();
728 if (!iMPP)
729 return info;
730 Lecture lecture = assignedPlacement.variable();
731 Placement initialPlacement = lecture.getInitialAssignment();
732 if (initialPlacement == null || initialPlacement.equals(assignedPlacement))
733 return info;
734 int perts = 1;
735 long affectedStudents = lecture.classLimit();
736 int affectedInstructors = lecture.getInstructorConstraints().size();
737 long affectedStudentsByTime = (initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation()) ? 0
738 : lecture.classLimit());
739 int affectedInstructorsByTime = (initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation()) ? 0
740 : lecture.getInstructorConstraints().size());
741
742 int differentRoom = initialPlacement.nrDifferentRooms(assignedPlacement);
743 int affectedInstructorsByRoom = differentRoom * lecture.getInstructorConstraints().size();
744 long affectedStudentsByRoom = differentRoom * lecture.classLimit();
745
746 int differentBuilding = initialPlacement.nrDifferentBuildings(initialPlacement);
747 int affectedInstructorsByBldg = differentBuilding * lecture.getInstructorConstraints().size();
748 long affectedStudentsByBldg = differentBuilding * lecture.classLimit();
749
750 int deltaRoomPreferences = assignedPlacement.sumRoomPreference() - initialPlacement.sumRoomPreference();
751
752 int differentTime = (initialPlacement.getTimeLocation().equals(assignedPlacement.getTimeLocation()) ? 0 : 1);
753 int differentDay = (initialPlacement.getTimeLocation().getDayCode() != assignedPlacement.getTimeLocation()
754 .getDayCode() ? 1 : 0);
755 int differentHour = (initialPlacement.getTimeLocation().getStartSlot() != assignedPlacement.getTimeLocation()
756 .getStartSlot() ? 1 : 0);
757 int tooFarForInstructors = 0;
758 int tooFarForStudents = 0;
759 int deltaStudentConflicts = lecture.countStudentConflicts(assignedPlacement)
760 - lecture.countInitialStudentConflicts();
761 int newStudentConflicts = 0;
762 double deltaTimePreferences = (assignedPlacement.getTimeLocation().getNormalizedPreference() - initialPlacement
763 .getTimeLocation().getNormalizedPreference());
764 int deltaInstructorDistancePreferences = 0;
765
766 double distance = Placement.getDistanceInMeters(iDistanceMetric, initialPlacement, assignedPlacement);
767 if (!lecture.getInstructorConstraints().isEmpty()) {
768 if (distance > iDistanceMetric.getInstructorNoPreferenceLimit() && distance <= iDistanceMetric.getInstructorDiscouragedLimit()) {
769 tooFarForInstructors += lecture.getInstructorConstraints().size();
770 } else if (distance > iDistanceMetric.getInstructorDiscouragedLimit() && distance <= iDistanceMetric.getInstructorProhibitedLimit()) {
771 tooFarForInstructors += 2 * lecture.getInstructorConstraints().size();
772 } else if (distance > iDistanceMetric.getInstructorProhibitedLimit()) {
773 tooFarForInstructors += 10 * lecture.getInstructorConstraints().size();
774 }
775 }
776 if (distance > iDistanceMetric.minutes2meters(10))
777 tooFarForStudents = lecture.classLimit();
778
779 Set<Student> newStudentConflictsVect = lecture.conflictStudents(assignedPlacement);
780 Set<Student> initialStudentConflicts = lecture.initialStudentConflicts();
781 for (Iterator<Student> e = newStudentConflictsVect.iterator(); e.hasNext();)
782 if (!initialStudentConflicts.contains(e.next()))
783 newStudentConflicts++;
784
785 for (InstructorConstraint ic : lecture.getInstructorConstraints()) {
786 for (Lecture lect : ic.variables()) {
787 if (lect.equals(lecture))
788 continue;
789 int initialPreference = (lect.getInitialAssignment() == null ? Constants.sPreferenceLevelNeutral : ic
790 .getDistancePreference(initialPlacement, lect.getInitialAssignment()));
791 int assignedPreference = (lect.getAssignment() == null ? Constants.sPreferenceLevelNeutral : ic
792 .getDistancePreference(assignedPlacement, lect.getAssignment()));
793 deltaInstructorDistancePreferences += (assignedPreference - initialPreference);
794 }
795 }
796
797 if (includeZero || iDifferentPlacement != 0.0)
798 info.put("Different placement", new Double(weighted ? iDifferentPlacement * perts : perts));
799 if (includeZero || iAffectedStudentWeight != 0.0)
800 info.put("Affected students", new Double(weighted ? iAffectedStudentWeight * affectedStudents
801 : affectedStudents));
802 if (includeZero || iAffectedInstructorWeight != 0.0)
803 info.put("Affected instructors", new Double(weighted ? iAffectedInstructorWeight * affectedInstructors
804 : affectedInstructors));
805 if (includeZero || iAffectedStudentByTimeWeight != 0.0)
806 info.put("Affected students [time]", new Double(weighted ? iAffectedStudentByTimeWeight
807 * affectedStudentsByTime : affectedStudentsByTime));
808 if (includeZero || iAffectedInstructorByTimeWeight != 0.0)
809 info.put("Affected instructors [time]", new Double(weighted ? iAffectedInstructorByTimeWeight
810 * affectedInstructorsByTime : affectedInstructorsByTime));
811 if (includeZero || iAffectedStudentByRoomWeight != 0.0)
812 info.put("Affected students [room]", new Double(weighted ? iAffectedStudentByRoomWeight
813 * affectedStudentsByRoom : affectedStudentsByRoom));
814 if (includeZero || iAffectedInstructorByRoomWeight != 0.0)
815 info.put("Affected instructors [room]", new Double(weighted ? iAffectedInstructorByRoomWeight
816 * affectedInstructorsByRoom : affectedInstructorsByRoom));
817 if (includeZero || iAffectedStudentByBldgWeight != 0.0)
818 info.put("Affected students [bldg]", new Double(weighted ? iAffectedStudentByBldgWeight
819 * affectedStudentsByBldg : affectedStudentsByBldg));
820 if (includeZero || iAffectedInstructorByBldgWeight != 0.0)
821 info.put("Affected instructors [bldg]", new Double(weighted ? iAffectedInstructorByBldgWeight
822 * affectedInstructorsByBldg : affectedInstructorsByBldg));
823 if (includeZero || iDifferentRoomWeight != 0.0)
824 info.put("Different room", new Double(weighted ? iDifferentRoomWeight * differentRoom : differentRoom));
825 if (includeZero || iDifferentBuildingWeight != 0.0)
826 info.put("Different building", new Double(weighted ? iDifferentBuildingWeight * differentBuilding
827 : differentBuilding));
828 if (includeZero || iDifferentTimeWeight != 0.0)
829 info.put("Different time", new Double(weighted ? iDifferentTimeWeight * differentTime : differentTime));
830 if (includeZero || iDifferentDayWeight != 0.0)
831 info.put("Different day", new Double(weighted ? iDifferentDayWeight * differentDay : differentDay));
832 if (includeZero || iDifferentHourWeight != 0.0)
833 info.put("Different hour", new Double(weighted ? iDifferentHourWeight * differentHour : differentHour));
834 if (includeZero || iTooFarForInstructorsWeight != 0.0)
835 info.put("New placement too far for initial [instructors]", new Double(
836 weighted ? iTooFarForInstructorsWeight * tooFarForInstructors : tooFarForInstructors));
837 if (includeZero || iTooFarForStudentsWeight != 0.0)
838 info.put("New placement too far for initial [students]", new Double(weighted ? iTooFarForStudentsWeight
839 * tooFarForStudents : tooFarForStudents));
840 if (includeZero || iDeltaStudentConflictsWeight != 0.0)
841 info.put("Delta student conflicts", new Double(weighted ? iDeltaStudentConflictsWeight
842 * deltaStudentConflicts : deltaStudentConflicts));
843 if (includeZero || iNewStudentConflictsWeight != 0.0)
844 info.put("New student conflicts", new Double(weighted ? iNewStudentConflictsWeight * newStudentConflicts
845 : newStudentConflicts));
846 if (includeZero || iDeltaTimePreferenceWeight != 0.0)
847 info.put("Delta time preferences", new Double(weighted ? iDeltaTimePreferenceWeight * deltaTimePreferences
848 : deltaTimePreferences));
849 if (includeZero || iDeltaRoomPreferenceWeight != 0.0)
850 info.put("Delta room preferences", new Double(weighted ? iDeltaRoomPreferenceWeight * deltaRoomPreferences
851 : deltaRoomPreferences));
852 if (includeZero || iDeltaInstructorDistancePreferenceWeight != 0.0)
853 info.put("Delta instructor distance preferences", new Double(
854 weighted ? iDeltaInstructorDistancePreferenceWeight * deltaInstructorDistancePreferences
855 : deltaInstructorDistancePreferences));
856 return info;
857 }
858 }