001 package ttsolver.model;
002
003
004 import ifs.model.*;
005 import ifs.util.*;
006
007 import java.util.*;
008
009 import ttsolver.*;
010 import ttsolver.constraint.*;
011
012 /**
013 * Lecture (variable).
014 *
015 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
016 * @version 1.0
017 */
018
019 public class Lecture extends Variable {
020 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(Lecture.class);
021 private long iClassId;
022 private String iName;
023 private String iDept;
024 private Vector iTimeLocations;
025 private Vector iRoomLocations;
026 private String iInstructorId;
027 private String iInstructorName;
028 private int iBestRoomPref;
029 private double iBestTimePref;
030 private long iNrStudents = -1;
031 private int iExpectedCapacity;
032 private Hashtable iSameRoomValues = null;
033 private String iPattern = null;
034
035 private Vector iStudents = new FastVector(1);
036 private Vector iAllStudents = null;
037 private Vector iSameLectures = null;
038 private Vector iCrossListedLectures = null;
039 private DepartmentSpreadConstraint iDeptSpreadConstrain = null;
040 private InstructorConstraint iInstructorConstraint = null;
041
042 //private Vector iDoneSwaps = new FastVector(1);
043
044 private Hashtable iSameStudents = new Hashtable(10);
045 private Vector iActiveJenrls = new FastVector(10);
046 private Vector iJenrlConstraints = new FastVector(10);
047
048 private static boolean sSaveMemory = false;
049
050 /** Constructor
051 * @param id unique identification
052 * @param name class name
053 * @param timeLocations set of time locations
054 * @param bestTimePref best time preference over all time locations
055 * @param instructorId instuctor id
056 * @param roomLocations set of room location
057 * @param bestRoomPref best room preference over all room locations
058 * @param initialPlacement initial placement
059 * @param expectedCapacity expected number of students
060 * @param inctructorName instructor name
061 * @param pattern time pattern (e.g., 2x100)
062 */
063 public Lecture(long id, String name, Vector timeLocations, double bestTimePref, String instructorId, Vector roomLocations, int bestRoomPref, Placement initialPlacement, int expectedCapacity, String inctructorName, String pattern) {
064 super(initialPlacement);
065 iClassId = id;
066 iTimeLocations = timeLocations;
067 iInstructorId = instructorId;
068 iInstructorName = inctructorName;
069 iRoomLocations = roomLocations;
070 iName = name;
071 iBestRoomPref = bestRoomPref;
072 iBestTimePref = bestTimePref;
073 iExpectedCapacity = expectedCapacity;
074 iPattern = pattern;
075 if (!sSaveMemory)
076 setValues(computeValues());
077 }
078
079 /** Add active jenrl constraint (active mean that there is at least one student between its classes) */
080 public void addActiveJenrl(JenrlConstraint constr) { iActiveJenrls.addElement(constr); }
081 /** Active jenrl constraints (active mean that there is at least one student between its classes) */
082 public Vector activeJenrls() { return iActiveJenrls; }
083 /** Remove active jenrl constraint (active mean that there is at least one student between its classes) */
084 public void removeActiveJenrl(JenrlConstraint constr) { iActiveJenrls.removeElement(constr); }
085
086 /** Class id */
087 public long getClassId() { return iClassId; }
088 /** Class name */
089 public String getName() { return iName; }
090 /** Class id */
091 public long getId() { return iClassId; }
092 /** Instructor name */
093 public String getInstructorName() { return iInstructorName; }
094 /** Instructor id */
095 public String getInstructorId() { return iInstructorId; }
096 /** List of enrolled students */
097 public Vector students() { return iStudents; }
098 /** List of enrolled students of this class and of all its cross-listed classes */
099 public Vector allStudents() { return (iAllStudents==null?iStudents:iAllStudents); }
100 /** Add an enrolled student */
101 public void addStudent(String student) {
102 iStudents.addElement(student);
103 if (iAllStudents!=null) iAllStudents.addElement(student);
104 }
105 /** Add a student enrolled to a cross-listed class */
106 public void addSameLectureStudent(String student) {
107 iAllStudents.addElement(student);
108 }
109 /** Returns true if the given student is enrolled */
110 public boolean hasStudent(String student) { return (iAllStudents==null?iStudents:iAllStudents).contains(student);}
111 /** Set of lectures of the same class (only section is different) */
112 public void setSameLectures(Vector sameLectures) { iSameLectures = sameLectures; }
113 /** Set of lectures of the same class (only section is different) */
114 public Vector sameLectures() { return iSameLectures; }
115 /* Set of cross-listed classes */
116 public Vector crossListedLectures() { return iCrossListedLectures; }
117 /* Set of cross-listed classes */
118 public void setCrossListedLectures(Vector crossListedLectures) {
119 iCrossListedLectures = crossListedLectures;
120 if (iCrossListedLectures!=null) {
121 iAllStudents = new FastVector(1);
122 for (Enumeration e2=iCrossListedLectures.elements();e2.hasMoreElements();)
123 ((CrossListedLecture)e2.nextElement()).setLecture(this);
124 }
125 }
126 /** List of students enrolled in this class as well as in the given class */
127 public Vector sameStudents(Lecture lecture) {
128 if (iSameStudents.containsKey(lecture)) return (Vector)iSameStudents.get(lecture);
129 Vector ret = new FastVector();
130 for (Enumeration e=allStudents().elements(); e.hasMoreElements();) {
131 String student = (String)e.nextElement();
132 if (lecture.allStudents().contains(student)) ret.addElement(student);
133 }
134 iSameStudents.put(lecture, ret);
135 return ret;
136 }
137 /** List of students which are in conflict with the given two classes */
138 public Vector conflictStudents(Value value, Variable anotherVariable) {
139 Vector ret = new FastVector();
140 if (value==null) return ret;
141 Lecture lecture = (Lecture)anotherVariable;
142 if (lecture.getAssignment()==null || lecture.equals(this)) return ret;
143 if (!JenrlConstraint.isInConflict((Placement)value,(Placement)lecture.getAssignment())) return ret;
144 return sameStudents(lecture);
145 }
146 /** List of students of this class in conflict with the given assignment */
147 public Vector conflictStudents(Value value) {
148 Vector ret = new FastVector();
149 if (value==null) return ret;
150 if (getAssignment()!=null && value.equals(getAssignment())) {
151 for (Enumeration i1=activeJenrls().elements(); i1.hasMoreElements();) {
152 JenrlConstraint jenrl = (JenrlConstraint) i1.nextElement();
153 ToolBox.merge(ret, sameStudents((Lecture)jenrl.another(this)));
154 }
155 } else {
156 for (Enumeration i1=iJenrlConstraints.elements(); i1.hasMoreElements();) { //constraints()
157 JenrlConstraint jenrl = (JenrlConstraint)i1.nextElement();// constraint;
158 if (jenrl.jenrl(this, value)>0)
159 ToolBox.merge(ret, sameStudents((Lecture)jenrl.another(this)));
160 }
161 }
162 return ret;
163 }
164
165 /** List of students of this class which are in conflict with any other assignment */
166 public Vector conflictStudents() {
167 Vector ret = new FastVector();
168 if (getAssignment()==null) return ret;
169 for (Enumeration i1=activeJenrls().elements(); i1.hasMoreElements();) {
170 JenrlConstraint jenrl = (JenrlConstraint) i1.nextElement();
171 ToolBox.merge(ret, sameStudents((Lecture)jenrl.another(this)));
172 }
173 return ret;
174 }
175
176 /** Lectures which share the given student, different from this one */
177 public Vector sameStudentLectures(String student) {
178 Vector ret = new FastVector();
179 for (Enumeration it=iJenrlConstraints.elements();it.hasMoreElements();) {//constraints()
180 JenrlConstraint jenrl = (JenrlConstraint)it.nextElement();
181 Lecture lect = (Lecture)jenrl.another(this);
182 if (!lect.equals(this) && lect.allStudents().contains(student)) ret.addElement(lect);
183 }
184 return ret;
185 }
186 /** Names of lectures different from this one, where it is student conflict of the given student between this and the lecture */
187 public Vector conflictLecturesNames(String student) {
188 Vector ret = new FastVector();
189 if (getAssignment()==null) return ret;
190 for (Enumeration it=activeJenrls().elements();it.hasMoreElements();) {
191 JenrlConstraint jenrl = (JenrlConstraint) it.nextElement();
192 Lecture lect = (Lecture)jenrl.another(this);
193 if (!lect.equals(this) && lect.allStudents().contains(student)) ret.addElement(lect.getName());
194 }
195 return ret;
196 }
197 /** Lectures different from this one, where it is student conflict of the given student between this and the lecture */
198 public Vector conflictLectures(String student) {
199 Vector ret = new FastVector();
200 if (getAssignment()==null) return ret;
201 for (Enumeration it=activeJenrls().elements();it.hasMoreElements();) {
202 JenrlConstraint jenrl = (JenrlConstraint) it.nextElement();
203 Lecture lect = (Lecture)jenrl.another(this);
204 if (lect.allStudents().contains(student)) ret.addElement(lect);
205 }
206 return ret;
207 }
208 /** Lectures different from this one, which are in a student conflict with the given assignment (of this lecture)*/
209 public Vector conflictLectures(Value value) {
210 Vector ret = new FastVector();
211 for (Enumeration it=iJenrlConstraints.elements();it.hasMoreElements();) {//constraints()
212 JenrlConstraint jenrl = (JenrlConstraint)it.nextElement();
213 Lecture lect = (Lecture)jenrl.another(this);
214 if (jenrl.jenrl(this, value)>0) ret.addElement(lect);
215 }
216 return ret;
217 }
218 /** Lectures different from this one, which are in a student conflict with the this lecture*/
219 public Vector conflictLectures() {
220 Vector ret = new FastVector();
221 for (Enumeration it=activeJenrls().elements();it.hasMoreElements();) {
222 JenrlConstraint jenrl = (JenrlConstraint) it.nextElement();
223 Lecture lect = (Lecture)jenrl.another(this);
224 ret.addElement(lect.getName());
225 }
226 return ret;
227
228 }
229 /** True if this lecture is in a student conflict with the given student */
230 public int isInConflict(String student) {
231 if (getAssignment()==null) return 0;
232 int ret = 0;
233 for (Enumeration it=activeJenrls().elements();it.hasMoreElements();) {
234 JenrlConstraint jenrl = (JenrlConstraint) it.nextElement();
235 Lecture lect = (Lecture)jenrl.another(this);
236 if (lect.allStudents().contains(student)) ret++;
237 }
238 return ret;
239 }
240 /** Swap students between this and the same lectures (lectures which differ only in the section) */
241 public Set swapStudents() {
242 if (iSameLectures==null || iStudents==null) return null;
243 if (getAssignment()==null) return null;
244 int totalConf = countStudentConflicts(getAssignment());
245 Vector conflictStudents = conflictStudents();
246 //sLogger.debug(" conflicts:"+totalConf+" "+conflictStudents);
247 if (totalConf==0) return null;
248 HashSet ret = new HashSet();
249 //sLogger.debug("Solution before swap is "+getModel().getInfo()+".");
250 if (iSameLectures.size()>1) for (Enumeration i1=conflictStudents.elements(); i1.hasMoreElements();) {
251 String student = (String)i1.nextElement();
252 int iniDelta=isInConflict(student);
253 if (iniDelta==0) continue;
254 int bestDelta=-1;
255 //sLogger.debug("student:"+student+", confs:"+iniDelta+" "+conflictLecturesNames(student));
256 Vector bestLecture=null;
257 Vector bestStudent=null;
258 for (Enumeration i2=iSameLectures.elements();i2.hasMoreElements();) {
259 Lecture sameLecture = (Lecture)i2.nextElement();
260 if (sameLecture.equals(this)) continue;
261 //if (sameLecture.isInConflict(student)<bestDelta) {
262 for (Enumeration i3=sameLecture.allStudents().elements();i3.hasMoreElements();) {
263 String anotherStudent = (String)i3.nextElement();
264 if (isSwapTabu(student,anotherStudent)) break;
265 if (bestDelta<0 && bestLecture!=null && bestLecture.size()>10) break;
266 int delta = isInConflict(anotherStudent)+sameLecture.isInConflict(student)-sameLecture.isInConflict(anotherStudent)-iniDelta;
267 if (delta<bestDelta) {
268 if (bestLecture==null) {
269 bestLecture=new FastVector(); bestStudent=new FastVector();
270 } else {
271 bestLecture.clear(); bestStudent.clear();
272 }
273 bestLecture.addElement(sameLecture);
274 bestStudent.addElement(anotherStudent);
275 bestDelta=delta;
276 } else if (delta==bestDelta) {
277 if (bestLecture==null) {
278 bestLecture=new FastVector(); bestStudent=new FastVector();
279 }
280 bestLecture.addElement(sameLecture);
281 bestStudent.addElement(anotherStudent);
282 } else continue;
283 //sLogger.debug("possible swap with "+anotherStudent+", confs:"+isInConflict(anotherStudent)+"+"+sameLecture.isInConflict(student)+"-"+sameLecture.isInConflict(anotherStudent)+"-"+iniDelta+", best:"+bestDelta);
284 }
285 if (bestDelta==0 && bestLecture!=null && bestLecture.size()>10) break;
286 //}
287 }
288 if (bestLecture!=null) {
289 int x = ToolBox.random(bestLecture.size());
290 //sLogger.debug("Swap "+getName()+" "+student+" <-> "+((Lecture)bestLecture.elementAt(x)).getName()+" "+(String)bestStudent.elementAt(x)+", delta:"+bestDelta);
291 //sLogger.debug(" -"+getName()+" "+student+": "+conflictLecturesNames(student));
292 //sLogger.debug(" +"+getName()+" "+(String)bestStudent.elementAt(x)+": "+conflictLecturesNames((String)bestStudent.elementAt(x)));
293 //sLogger.debug(" -"+((Lecture)bestLecture.elementAt(x)).getName()+" "+(String)bestStudent.elementAt(x)+": "+((Lecture)bestLecture.elementAt(x)).conflictLecturesNames((String)bestStudent.elementAt(x)));
294 //sLogger.debug(" +"+((Lecture)bestLecture.elementAt(x)).getName()+" "+student+": "+((Lecture)bestLecture.elementAt(x)).conflictLecturesNames(student));
295 swap(student, (Lecture)bestLecture.elementAt(x), (String)bestStudent.elementAt(x), bestDelta);
296 ret.add(bestLecture.elementAt(x));
297 //sLogger.debug("Solution after swap is "+getModel().getInfo()+".");
298 } else {
299 //sLogger.debug("no swap found");
300 }
301 } else for (Enumeration i1=conflictStudents.elements(); i1.hasMoreElements();) { //no same lecture
302 String student = (String)i1.nextElement();
303 int iniDelta=isInConflict(student);
304 if (iniDelta==0) continue;
305 int bestDelta=iniDelta;
306 //sLogger.debug("student:"+student+", confs:"+bestDelta+" "+conflictLecturesNames(student));
307 for (Enumeration i2=conflictLectures(student).elements(); i2.hasMoreElements();) {
308 Lecture anotherLecture = (Lecture)i2.nextElement();
309 if (!anotherLecture.equals(this) && anotherLecture.getAssignment()!=null && anotherLecture.sameLectures().size()>1) {
310 Set lects = anotherLecture.swapStudents();
311 if (lects!=null) ret.addAll(lects);
312 }
313 }
314 }
315 return ret;
316 }
317 /** Prohibited swaps */
318 public boolean isSwapTabu(String student, String swapStudent) {
319 return false;
320 //return iDoneSwaps.contains(student+","+swapStudent);
321 }
322 /** Swap two students between this and swapLecture*/
323 private void justSwap(String student, Lecture swapLecture, String swapStudent) {
324 Vector source = null, target = null;
325 if (iAllStudents==null || iStudents.contains(student)) source = iStudents;
326 else {
327 for (Enumeration e=iCrossListedLectures.elements();source==null && e.hasMoreElements();) {
328 CrossListedLecture sl = (CrossListedLecture)e.nextElement();
329 if (sl.students().contains(student)) source=sl.students();
330 }
331 }
332 if (swapLecture.iAllStudents==null || swapLecture.iStudents.contains(swapStudent)) target = swapLecture.iStudents;
333 else {
334 for (Enumeration e=swapLecture.iCrossListedLectures.elements();target==null && e.hasMoreElements();) {
335 CrossListedLecture sl = (CrossListedLecture)e.nextElement();
336 if (sl.students().contains(swapStudent)) target=sl.students();
337 }
338 }
339 target.setElementAt(student, target.indexOf(swapStudent));
340 source.setElementAt(swapStudent, source.indexOf(student));
341 if (iAllStudents!=null)
342 iAllStudents.setElementAt(swapStudent, iAllStudents.indexOf(student));
343 if (swapLecture.iAllStudents!=null)
344 swapLecture.iAllStudents.setElementAt(student, swapLecture.iAllStudents.indexOf(swapStudent));
345 //swapLecture.iStudents.setElementAt(student, swapLecture.iStudents.indexOf(swapStudent));
346 //iStudents.setElementAt(swapStudent, iStudents.indexOf(student));
347 }
348 /** Swap two students between this and swapLecture*/
349 private void swap(String student, Lecture swapLecture, String swapStudent, int delta) {
350 //iDoneSwaps.addElement(student+","+swapStudent);
351 Vector jenrlsToRemove = new FastVector();
352 for (Enumeration it=iJenrlConstraints.elements();it.hasMoreElements();) {
353 JenrlConstraint jenrl = (JenrlConstraint)it.nextElement();
354 for (Enumeration it2=jenrl.variables().elements();it2.hasMoreElements();) {
355 Lecture anotherLecture = (Lecture)it2.nextElement();
356 if (anotherLecture.equals(this)) continue;
357 if (anotherLecture.allStudents().contains(student)) {
358 //sLogger.debug(getName()+": jenr-- {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
359 jenrl.decJenrl();
360 if (jenrl.getJenrl()==0) {
361 jenrlsToRemove.addElement(jenrl);
362 //sLogger.debug(getName()+": remove jenr {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
363 }
364 }
365 }
366 }
367 for (Enumeration it=swapLecture.iJenrlConstraints.elements();it.hasMoreElements();) {
368 JenrlConstraint jenrl = (JenrlConstraint)it.nextElement();
369 for (Enumeration it2=jenrl.variables().elements();it2.hasMoreElements();) {
370 Lecture anotherLecture = (Lecture)it2.nextElement();
371 if (anotherLecture.equals(swapLecture)) continue;
372 if (anotherLecture.allStudents().contains(swapStudent)) {
373 //sLogger.debug(swapLecture.getName()+": jenr-- {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
374 jenrl.decJenrl();
375 if (jenrl.getJenrl()==0) {
376 jenrlsToRemove.addElement(jenrl);
377 //sLogger.debug(swapLecture.getName()+": remove jenr {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
378 }
379 }
380 }
381 }
382 if (!jenrlsToRemove.isEmpty()) {
383 Object[] delete = jenrlsToRemove.toArray();
384 for (int i=0;i<delete.length;i++) {
385 Constraint c = (Constraint)delete[i];
386 Object[] vars = c.variables().toArray();
387 for (int j=0;j<vars.length;j++)
388 c.removeVariable((Variable)vars[j]);
389 getModel().removeConstraint(c);
390 }
391 }
392 justSwap(student, swapLecture, swapStudent);
393 swapLecture.iSameStudents.clear();
394 iSameStudents.clear();
395 Vector jenrlsToAdd = new FastVector();
396 for (Enumeration it=getModel().variables().elements(); it.hasMoreElements();) {
397 Lecture anotherLecture = (Lecture)it.nextElement();
398 if (anotherLecture.equals(this) || anotherLecture.equals(swapLecture)) continue;
399 if (anotherLecture.allStudents().contains(swapStudent)) {
400 boolean found = false;
401 for (Enumeration itc=iJenrlConstraints.elements();!found && itc.hasMoreElements();) {
402 JenrlConstraint jenrl = (JenrlConstraint)itc.nextElement();
403 for (Enumeration it2=jenrl.variables().elements();it2.hasMoreElements();) {
404 Lecture xLecture = (Lecture)it2.nextElement();
405 if (xLecture.equals(anotherLecture)) {
406 found = true;
407 //sLogger.debug(getName()+": jenr++ {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
408 jenrl.incJenrl();
409 }
410 }
411 }
412 if (!found) {
413 JenrlConstraint jenrl = new JenrlConstraint(1, ((TimetableModel)getModel()).getViolatedStudentConflictsCounter());
414 jenrl.addVariable(this);
415 jenrl.addVariable(anotherLecture);
416 //sLogger.debug(getName()+": add jenr {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
417 jenrlsToAdd.addElement(jenrl);
418 }
419 }
420 if (anotherLecture.allStudents().contains(student)) {
421 boolean found = false;
422 for (Enumeration itc=swapLecture.iJenrlConstraints.elements();!found && itc.hasMoreElements();) {
423 JenrlConstraint jenrl = (JenrlConstraint)itc.nextElement();
424 for (Enumeration it2=jenrl.variables().elements();it2.hasMoreElements();) {
425 Lecture xLecture = (Lecture)it2.nextElement();
426 if (xLecture.equals(anotherLecture)) {
427 found = true;
428 //sLogger.debug(swapLecture.getName()+": jenr++ {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
429 jenrl.incJenrl();
430 }
431 }
432 }
433 if (!found) {
434 JenrlConstraint jenrl = new JenrlConstraint(1, ((TimetableModel)getModel()).getViolatedStudentConflictsCounter());
435 jenrl.addVariable(swapLecture);
436 jenrl.addVariable(anotherLecture);
437 //sLogger.debug(swapLecture.getName()+": add jenr {conf="+jenrl.isInConflict()+", lect="+anotherLecture.getName()+", jenr="+jenrl+"}");
438 jenrlsToAdd.addElement(jenrl);
439 }
440 }
441 }
442 if (!jenrlsToAdd.isEmpty()) {
443 Object[] add = jenrlsToAdd.toArray();
444 for (int i=0;i<add.length;i++)
445 getModel().addConstraint((Constraint)add[i]);
446 }
447 }
448
449 /** Domain -- all combinations of room and time locations */
450 public Vector computeValues() {
451 Vector values = new FastVector();
452 iSameRoomValues = new Hashtable();
453 for (Enumeration i2=iRoomLocations.elements();i2.hasMoreElements();) {
454 RoomLocation roomLocation = (RoomLocation)i2.nextElement();
455 Vector placements = new FastVector();
456 for (Enumeration i1=iTimeLocations.elements();i1.hasMoreElements();) {
457 TimeLocation timeLocation = (TimeLocation)i1.nextElement();
458 Placement p = new Placement(this,timeLocation, roomLocation);
459 p.setVariable(this);
460 if (getInitialAssignment()!=null && p.equals(getInitialAssignment())) {
461 setInitialAssignment(p);
462 p.setInitial(true);
463 }
464 if (getAssignment()!=null && getAssignment().equals(p)) iValue=getAssignment();
465 if (getBestAssignment()!=null && getBestAssignment().equals(p)) setBestAssignment(p);
466 values.addElement(p);
467 placements.addElement(p);
468 }
469 iSameRoomValues.put(roomLocation.getId(),placements);
470 }
471 return values;
472 }
473
474 /** All values which uses the given room */
475 public Vector getSameRoomValues(String roomId) {
476 if (sSaveMemory) {
477 for (Enumeration i2=iRoomLocations.elements();i2.hasMoreElements();) {
478 RoomLocation roomLocation = (RoomLocation)i2.nextElement();
479 if (!roomLocation.getId().equals(roomId)) continue;
480 Vector placements = new FastVector();
481 for (Enumeration i1=iTimeLocations.elements();i1.hasMoreElements();) {
482 TimeLocation timeLocation = (TimeLocation)i1.nextElement();
483 Placement p = new Placement(this,timeLocation, roomLocation);
484 p.setVariable(this);
485 if (getInitialAssignment()!=null && p.equals(getInitialAssignment())) {
486 setInitialAssignment(p);
487 p.setInitial(true);
488 }
489 if (getAssignment()!=null && getAssignment().equals(p)) iValue=getAssignment();
490 if (getBestAssignment()!=null && getBestAssignment().equals(p)) setBestAssignment(p);
491 placements.addElement(p);
492 }
493 return placements;
494 }
495 }
496 return (Vector)iSameRoomValues.get(roomId);
497 }
498
499 /** All values */
500 public Vector values() {
501 if (sSaveMemory) {
502 Vector values = new FastVector(iRoomLocations.size()*iTimeLocations.size());
503 for (Enumeration i2=iRoomLocations.elements();i2.hasMoreElements();) {
504 RoomLocation roomLocation = (RoomLocation)i2.nextElement();
505 Vector placements = new FastVector();
506 for (Enumeration i1=iTimeLocations.elements();i1.hasMoreElements();) {
507 TimeLocation timeLocation = (TimeLocation)i1.nextElement();
508 Placement p = new Placement(this,timeLocation, roomLocation);
509 p.setVariable(this);
510 if (getInitialAssignment()!=null && p.equals(getInitialAssignment())) {
511 setInitialAssignment(p);
512 p.setInitial(true);
513 }
514 if (getAssignment()!=null && getAssignment().equals(p)) iValue=getAssignment();
515 if (getBestAssignment()!=null && getBestAssignment().equals(p)) setBestAssignment(p);
516 values.addElement(p);
517 }
518 }
519 return values;
520 } else
521 return super.values();
522 }
523
524 public boolean equals(Object o) {
525 try {
526 return getId()==((Lecture)o).getId();
527 } catch (Exception e) {
528 return false;
529 }
530 }
531
532 /** Best time preference of this lecture */
533 public double getBestTimePreference() { return iBestTimePref; }
534 /** Best room preference of this lecture */
535 public int getBestRoomPreference() { return iBestRoomPref; }
536
537 /** Number of student conflicts caused by the given assignment of this lecture */
538 public int countStudentConflicts(Value value) {
539 int studentConflictsSum = 0;
540 for (Enumeration i=jenrlConstraints().elements();i.hasMoreElements();) {
541 JenrlConstraint jenrl = (JenrlConstraint)i.nextElement();
542 studentConflictsSum += jenrl.jenrl(this, value);
543 }
544 return studentConflictsSum;
545 }
546
547 /** Number of student conflicts caused by the initial assignment of this lecture */
548 public int countInitialStudentConflicts() {
549 Value value = getInitialAssignment();
550 if (value==null) return 0;
551 int studentConflictsSum = 0;
552 for (Enumeration i=jenrlConstraints().elements();i.hasMoreElements();) {
553 JenrlConstraint jenrl = (JenrlConstraint)i.nextElement();
554 Lecture another = (Lecture)jenrl.another(this);
555 if (another.getInitialAssignment()!=null)
556 if (JenrlConstraint.isInConflict((Placement)value,(Placement)another.getInitialAssignment()))
557 studentConflictsSum += jenrl.getJenrl();
558 }
559 return studentConflictsSum;
560 }
561
562 /** Table of student conflicts caused by the initial assignment of this lecture in format (another lecture, number)*/
563 public Hashtable getInitialStudentConflicts() {
564 Value value = getInitialAssignment();
565 if (value==null) return null;
566 Hashtable ret = new Hashtable();
567 for (Enumeration i=jenrlConstraints().elements();i.hasMoreElements();) {
568 JenrlConstraint jenrl = (JenrlConstraint)i.nextElement();
569 Lecture another = (Lecture)jenrl.another(this);
570 if (another.getInitialAssignment()!=null)
571 if (JenrlConstraint.isInConflict((Placement)value,(Placement)another.getInitialAssignment()))
572 ret.put(another,new Long(jenrl.getJenrl()));
573 }
574 return ret;
575 }
576
577 /** List of student conflicts caused by the initial assignment of this lecture */
578 public Set initialStudentConflicts() {
579 Value value = getInitialAssignment();
580 if (value==null) return null;
581 HashSet ret = new HashSet();
582 for (Enumeration i=jenrlConstraints().elements();i.hasMoreElements();) {
583 JenrlConstraint jenrl = (JenrlConstraint)i.nextElement();
584 Lecture another = (Lecture)jenrl.another(this);
585 if (another.getInitialAssignment()!=null)
586 if (JenrlConstraint.isInConflict((Placement)value,(Placement)another.getInitialAssignment()))
587 ret.addAll(sameStudents(another));
588 }
589 return ret;
590 }
591
592 public void addContstraint(Constraint constraint) {
593 super.addContstraint(constraint);
594 if (constraint instanceof JenrlConstraint)
595 iJenrlConstraints.addElement(constraint);
596 else if (constraint instanceof DepartmentSpreadConstraint)
597 iDeptSpreadConstrain = (DepartmentSpreadConstraint)constraint;
598 else if (constraint instanceof InstructorConstraint)
599 iInstructorConstraint = (InstructorConstraint)constraint;
600 }
601 public void removeContstraint(Constraint constraint) {
602 super.removeContstraint(constraint);
603 if (iJenrlConstraints.contains(constraint))
604 iJenrlConstraints.removeElement(constraint);
605 }
606
607 /** All JENRL constraints of this lecture */
608 public Vector jenrlConstraints() {
609 return iJenrlConstraints;
610 }
611
612 /** Expected capacity */
613 public long countStudents() {
614 return iExpectedCapacity;
615 /*if (iNrStudents>=0) return iNrStudents;
616 long ret = 0;
617 for (Enumeration i=jenrlConstraints().elements();i.hasMoreElements();) {
618 ret += ((JenrlConstraint)i.nextElement()).getJenrl();
619 }
620 iNrStudents = ret;
621 ToolBox.print("Class "+getName()+" has "+ret+(students()==null?"":" ("+students().size()+")")+" students.");
622 return ret;*/
623 }
624
625 public String toString() {
626 return getName()+" ["+getDescription()+"]";//"Lecture{name='"+getName()+"', time="+(getAssignment()==null?"?":String.valueOf(((Placement)getAssignment()).getTimeLocation().getNormalizedPreference()))+"/"+iBestTimePref+", room="+(getAssignment()==null?"?":String.valueOf(((Placement)getAssignment()).getRoomLocation().getPreference()))+"/"+iBestRoomPref+", super="+super.toString()+"}";
627 }
628
629 /** Description */
630 public String getDescription() {
631 return (iPattern==null?"":iPattern+", ")+iExpectedCapacity+" exp. students"+
632 (iBestTimePref!=0?", "+iBestTimePref+" best time pref.":"")+
633 (iBestRoomPref!=0?", "+iBestRoomPref+" best room pref.":"")+
634 (getInitialAssignment()==null?"":", initial "+getInitialAssignment().getName())+
635 ", "+(values().size()==1?"value "+((Placement)values().firstElement()).getName()+" required":values().size()<=5?"values=["+getValuesString()+"]":values().size()+" values");
636 }
637
638 public String getValuesString() {
639 StringBuffer sb = new StringBuffer();
640 for (Enumeration e=values().elements();e.hasMoreElements();) {
641 Placement p = (Placement)e.nextElement();
642 sb.append(p.getName()).append(e.hasMoreElements()?", ":"");
643 }
644 return sb.toString();
645 }
646
647 /** Department */
648 public String getDepartment() { return iDept;}
649 /** Department */
650 public void setDepartment(String dept) { iDept=dept; }
651 /** Departmental spreading constraint */
652 public DepartmentSpreadConstraint getDeptSpreadConstraint() { return iDeptSpreadConstrain; }
653 /** Instructor constraint */
654 public InstructorConstraint getInstructorConstraint() { return iInstructorConstraint; }
655 /** All room locations */
656 public Vector roomLocations() { return iRoomLocations; }
657 /** All time locations */
658 public Vector timeLocations() { return iTimeLocations; }
659 }