001package org.cpsolver.coursett.constraint;
002
003import java.util.ArrayList;
004import java.util.BitSet;
005import java.util.Collection;
006import java.util.Enumeration;
007import java.util.HashSet;
008import java.util.List;
009import java.util.Set;
010
011import org.cpsolver.coursett.Constants;
012import org.cpsolver.coursett.criteria.BrokenTimePatterns;
013import org.cpsolver.coursett.criteria.UselessHalfHours;
014import org.cpsolver.coursett.model.Lecture;
015import org.cpsolver.coursett.model.Placement;
016import org.cpsolver.coursett.model.RoomSharingModel;
017import org.cpsolver.coursett.model.TimeLocation;
018import org.cpsolver.coursett.model.TimetableModel;
019import org.cpsolver.ifs.assignment.Assignment;
020import org.cpsolver.ifs.assignment.context.AssignmentConstraintContext;
021import org.cpsolver.ifs.assignment.context.ConstraintWithContext;
022import org.cpsolver.ifs.model.Model;
023import org.cpsolver.ifs.util.DataProperties;
024
025
026/**
027 * Room constraint. <br>
028 * Classes with the same room can not overlap in time.
029 * 
030 * @author  Tomáš Müller
031 * @version CourseTT 1.3 (University Course Timetabling)<br>
032 *          Copyright (C) 2006 - 2014 Tomáš Müller<br>
033 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
034 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
035 * <br>
036 *          This library is free software; you can redistribute it and/or modify
037 *          it under the terms of the GNU Lesser General Public License as
038 *          published by the Free Software Foundation; either version 3 of the
039 *          License, or (at your option) any later version. <br>
040 * <br>
041 *          This library is distributed in the hope that it will be useful, but
042 *          WITHOUT ANY WARRANTY; without even the implied warranty of
043 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
044 *          Lesser General Public License for more details. <br>
045 * <br>
046 *          You should have received a copy of the GNU Lesser General Public
047 *          License along with this library; if not see
048 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
049 */
050
051public class RoomConstraint extends ConstraintWithContext<Lecture, Placement, RoomConstraint.RoomConstraintContext> {
052    private Long iResourceId;
053    private String iName;
054    private Long iBuildingId;
055    private int iCapacity = 0;
056    private List<Placement>[] iAvailable = null;
057    private boolean iConstraint = true;
058
059    private Double iPosX = null, iPosY = null;
060    private boolean iIgnoreTooFar = false;
061
062    private RoomSharingModel iRoomSharingModel = null;
063
064    private Long iType = null;
065    private int iDayOfWeekOffset = 0;
066    
067    private RoomConstraint iParentRoom;
068    private List<RoomConstraint> iPartitions;
069
070    /**
071     * Constructor
072     * @param id room unique id
073     * @param name room name
074     * @param buildingId building unique id
075     * @param capacity room size
076     * @param roomSharingModel room sharing model
077     * @param x X-coordinate (latitude)
078     * @param y Y-coordinate (longitude)
079     * @param ignoreTooFar ignore distances if set to true
080     * @param constraint hard constraint if true (classes cannot overlap in this room)
081     */
082    public RoomConstraint(Long id, String name, Long buildingId, int capacity, RoomSharingModel roomSharingModel,
083            Double x, Double y, boolean ignoreTooFar, boolean constraint) {
084        iResourceId = id;
085        iName = name;
086        iBuildingId = buildingId;
087        iCapacity = capacity;
088        iConstraint = constraint;
089        iRoomSharingModel = roomSharingModel;
090        iPosX = x;
091        iPosY = y;
092        iIgnoreTooFar = ignoreTooFar;
093    }
094    
095    @Override
096    public void setModel(Model<Lecture, Placement> model) {
097        super.setModel(model);
098        if (model != null) {
099            DataProperties config = ((TimetableModel)model).getProperties();
100            iDayOfWeekOffset = config.getPropertyInt("DatePattern.DayOfWeekOffset", 0);
101        }
102    }
103
104    @SuppressWarnings("unchecked")
105    public void setNotAvailable(Placement placement) {
106        if (iAvailable == null) {
107            iAvailable = new List[Constants.SLOTS_PER_DAY * Constants.NR_DAYS];
108            for (int i = 0; i < iAvailable.length; i++)
109                iAvailable[i] = null;
110        }
111        for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
112            int slot = e.nextElement();
113            if (iAvailable[slot] == null)
114                iAvailable[slot] = new ArrayList<Placement>(1);
115            iAvailable[slot].add(placement);
116        }
117        for (Lecture lecture: variables())
118            lecture.clearValueCache();
119    }
120
121    public boolean isAvailable(int slot) {
122        if (getConstraint() && iAvailable != null && iAvailable[slot] != null && !iAvailable[slot].isEmpty())
123            return false;
124        if (getSharingModel() != null && getSharingModel().isNotAvailable(slot))
125            return false;
126        return true;
127    }
128
129    public boolean isAvailable(Lecture lecture, TimeLocation time, Long scheduler) {
130        if (iAvailable != null && getConstraint()) {
131            for (Enumeration<Integer> e = time.getSlots(); e.hasMoreElements();) {
132                int slot = e.nextElement();
133                if (iAvailable[slot] != null) {
134                    for (Placement p : iAvailable[slot]) {
135                        if (lecture.canShareRoom(p.variable()))
136                            continue;
137                        if (time.shareWeeks(p.getTimeLocation()))
138                            return false;
139                    }
140                }
141            }
142        }
143
144        // room partition checking
145        if (getParentRoom() != null && getParentRoom().getConstraint() && getParentRoom().iAvailable != null) { // check parent room's availability
146            for (Enumeration<Integer> e = time.getSlots(); e.hasMoreElements();) {
147                int slot = e.nextElement();
148                if (getParentRoom().iAvailable[slot] != null) {
149                    for (Placement p : getParentRoom().iAvailable[slot]) {
150                        if (lecture.canShareRoom(p.variable()))
151                            continue;
152                        if (time.shareWeeks(p.getTimeLocation()))
153                            return false;
154                    }
155                }
156            }
157        }
158        if (getPartitions() != null) { // check partitions for availability
159            for (RoomConstraint partition: getPartitions()) {
160                if (partition.iAvailable != null && partition.getConstraint()) {
161                    for (Enumeration<Integer> e = time.getSlots(); e.hasMoreElements();) {
162                        int slot = e.nextElement();
163                        if (partition.iAvailable[slot] != null) {
164                            for (Placement p : partition.iAvailable[slot]) {
165                                if (lecture.canShareRoom(p.variable()))
166                                    continue;
167                                if (time.shareWeeks(p.getTimeLocation()))
168                                    return false;
169                            }
170                        }
171                    }
172                }
173            }
174        }
175        
176        if (getSharingModel() != null && !getSharingModel().isAvailable(time, scheduler))
177            return false;
178        return true;
179    }
180
181    public List<Placement>[] getAvailableArray() {
182        return iAvailable;
183    }
184
185    public RoomSharingModel getSharingModel() {
186        return iRoomSharingModel;
187    }
188    
189    /**
190     * Add partition of this room. This room is unavailable at a time when one of the partition 
191     * is not available and vice versa.
192     * @param room room partition
193     */
194    public void addPartition(RoomConstraint room) {
195        room.iParentRoom = this;
196        if (iPartitions == null) iPartitions = new ArrayList<RoomConstraint>();
197        iPartitions.add(room);
198    }
199    
200    /**
201     * If this room is a partition of some other room, returns the parent room (which is partitioned).
202     * @return parent room
203     */
204    public RoomConstraint getParentRoom() { return iParentRoom; }
205    
206    /**
207     * If this room is partitioned into multiple rooms, return room partitions
208     * @return room partitions
209     */
210    public List<RoomConstraint> getPartitions() { return iPartitions; }
211
212    /** Room id 
213     * @return room unique id
214     **/
215    public Long getResourceId() {
216        return iResourceId;
217    }
218
219    /** Building id 
220     * @return building unique id
221     **/
222    public Long getBuildingId() {
223        return iBuildingId;
224    }
225
226    /** Room name */
227    @Override
228    public String getName() {
229        return iName;
230    }
231
232    public String getRoomName() {
233        return iName;
234    }
235
236    /** Capacity 
237     * @return room size
238     **/
239    public int getCapacity() {
240        return iCapacity;
241    }
242
243    @Override
244    public void computeConflicts(Assignment<Lecture, Placement> assignment, Placement placement, Set<Placement> conflicts) {
245        if (!getConstraint())
246            return;
247        if (!placement.hasRoomLocation(getResourceId()))
248            return;
249
250        // room partition checking
251        if (getParentRoom() != null && getParentRoom().getConstraint()) { // check parent room's availability
252            Lecture lecture = placement.variable();
253            Placement current = assignment.getValue(lecture);
254            Set<Placement> shared = null;
255            BitSet weekCode = placement.getTimeLocation().getWeekCode();
256            RoomConstraintContext context = getParentRoom().getContext(assignment);
257            for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
258                int slot = e.nextElement();
259                for (Placement confPlacement : context.getPlacements(slot)) {
260                    if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
261                        continue;
262                    if (confPlacement.equals(current))
263                        continue;
264                    if (shared != null && shared.contains(confPlacement))
265                        continue;
266                    if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
267                        if (shared == null) shared = new HashSet<Placement>();
268                        shared.add(confPlacement);
269                        continue;
270                    }
271                    conflicts.add(confPlacement);
272                }
273            }
274        }
275        if (getPartitions() != null) { // check partitions for availability
276            Lecture lecture = placement.variable();
277            Placement current = assignment.getValue(lecture);
278            Set<Placement> shared = null;
279            BitSet weekCode = placement.getTimeLocation().getWeekCode();
280            for (RoomConstraint partition: iPartitions) {
281                if (!partition.getConstraint()) continue;
282                RoomConstraintContext context = partition.getContext(assignment);
283                for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
284                    int slot = e.nextElement();
285                    for (Placement confPlacement : context.getPlacements(slot)) {
286                        if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
287                            continue;
288                        if (confPlacement.equals(current))
289                            continue;
290                        if (shared != null && shared.contains(confPlacement))
291                            continue;
292                        if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
293                            if (shared == null) shared = new HashSet<Placement>();
294                            shared.add(confPlacement);
295                            continue;
296                        }
297                        conflicts.add(confPlacement);
298                    }
299                }
300            }
301        }
302        
303        Lecture lecture = placement.variable();
304        Placement current = assignment.getValue(lecture);
305        Set<Placement> shared = null;
306        BitSet weekCode = placement.getTimeLocation().getWeekCode();
307        RoomConstraintContext context = getContext(assignment);
308
309        for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
310            int slot = e.nextElement();
311            for (Placement confPlacement : context.getPlacements(slot)) {
312                if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
313                    continue;
314                if (confPlacement.equals(current))
315                    continue;
316                if (shared != null && shared.contains(confPlacement))
317                    continue;
318                if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
319                    if (shared == null) shared = new HashSet<Placement>();
320                    shared.add(confPlacement);
321                    continue;
322                }
323                conflicts.add(confPlacement);
324            }
325        }
326    }
327    
328    public boolean checkRoomSize(Placement placement, Collection<Placement> other, Placement extra) {
329        int day = -1;
330        TimeLocation t1 = placement.getTimeLocation();
331        while ((day = t1.getWeekCode().nextSetBit(1 + day)) >= 0) {
332            int dow = (day + iDayOfWeekOffset) % 7;
333            if ((t1.getDayCode() & Constants.DAY_CODES[dow]) == 0) continue;
334            if (extra != null) {
335                TimeLocation t2 = extra.getTimeLocation();
336                if (!t2.hasDay(day) || (t2.getDayCode() & Constants.DAY_CODES[dow]) == 0) continue;
337            }
338            for (int i = 0; i < t1.getLength(); i++) {
339                int slot = t1.getStartSlot() + i;
340                int size = placement.variable().maxRoomUse();
341                if (extra != null) {
342                    TimeLocation t2 = extra.getTimeLocation();
343                    if (t2.getStartSlot() <= slot && slot < t2.getStartSlot() + t2.getLength())
344                        size += extra.variable().maxRoomUse();
345                    else
346                        continue;
347                }
348                if (other != null)
349                    for (Placement p: other) {
350                        TimeLocation t2 = p.getTimeLocation();
351                        if (t2.hasDay(day) && (t2.getDayCode() & Constants.DAY_CODES[dow]) != 0 && t2.getStartSlot() <= slot && slot < t2.getStartSlot() + t2.getLength())
352                            size += p.variable().maxRoomUse();
353                    }
354                if (size > getCapacity()) {
355                    return false;
356                }
357            }
358        }
359        return true;
360    }
361
362    public boolean checkRoomSize(Placement placement, Collection<Placement> other) {
363        return checkRoomSize(placement, other, null);
364    }
365
366    @Override
367    public boolean inConflict(Assignment<Lecture, Placement> assignment, Placement placement) {
368        if (!getConstraint())
369            return false;
370        if (!placement.hasRoomLocation(getResourceId()))
371            return false;
372        
373        // room partition checking
374        if (getParentRoom() != null && getParentRoom().getConstraint()) { // check parent room's availability
375            Lecture lecture = placement.variable();
376            Placement current = assignment.getValue(lecture);
377            Set<Placement> shared = null;
378            BitSet weekCode = placement.getTimeLocation().getWeekCode();
379            RoomConstraintContext context = getParentRoom().getContext(assignment);
380            for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
381                int slot = e.nextElement();
382                for (Placement confPlacement : context.getPlacements(slot)) {
383                    if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
384                        continue;
385                    if (confPlacement.equals(current))
386                        continue;
387                    if (shared != null && shared.contains(confPlacement))
388                        continue;
389                    if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
390                        if (shared == null) shared = new HashSet<Placement>();
391                        shared.add(confPlacement);
392                        continue;
393                    }
394                    return true;
395                }
396            }
397        }
398        if (getPartitions() != null) { // check partitions for availability
399            Lecture lecture = placement.variable();
400            Placement current = assignment.getValue(lecture);
401            Set<Placement> shared = null;
402            BitSet weekCode = placement.getTimeLocation().getWeekCode();
403            for (RoomConstraint partition: iPartitions) {
404                if (!partition.getConstraint()) continue;
405                RoomConstraintContext context = partition.getContext(assignment);
406                for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
407                    int slot = e.nextElement();
408                    for (Placement confPlacement : context.getPlacements(slot)) {
409                        if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
410                            continue;
411                        if (confPlacement.equals(current))
412                            continue;
413                        if (shared != null && shared.contains(confPlacement))
414                            continue;
415                        if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
416                            if (shared == null) shared = new HashSet<Placement>();
417                            shared.add(confPlacement);
418                            continue;
419                        }
420                        return true;
421                    }
422                }
423            }
424        }
425
426        Lecture lecture = placement.variable();
427        Placement current = assignment.getValue(lecture);
428        Set<Placement> shared = null;
429        BitSet weekCode = placement.getTimeLocation().getWeekCode();
430        RoomConstraintContext context = getContext(assignment);
431
432        for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
433            int slot = e.nextElement();
434            for (Placement confPlacement : context.getPlacements(slot)) {
435                if (!confPlacement.getTimeLocation().shareWeeks(weekCode))
436                    continue;
437                if (confPlacement.equals(current))
438                    continue;
439                if (shared != null && shared.contains(confPlacement))
440                    continue;
441                if (confPlacement.canShareRooms(placement) && checkRoomSize(placement, shared, confPlacement)) {
442                    if (shared == null) shared = new HashSet<Placement>();
443                    shared.add(confPlacement);
444                    continue;
445                }
446                return true;
447            }
448        }
449        return false;
450    }
451
452    @Override
453    public boolean isConsistent(Placement p1, Placement p2) {
454        if (!getConstraint())
455            return true;
456        if (getParentRoom() != null) { // partition checking -- one of the placement is with the parent room
457            if ((p1.hasRoomLocation(getResourceId()) && p2.hasRoomLocation(getParentRoom().getResourceId())) ||
458                (p2.hasRoomLocation(getResourceId()) && p1.hasRoomLocation(getParentRoom().getResourceId()))) {
459                if (p1.getTimeLocation().hasIntersection(p2.getTimeLocation())) {
460                    if (!p1.canShareRooms(p2) || (p1.variable()).maxRoomUse() + (p2.variable()).maxRoomUse() > getCapacity())
461                        return true;
462                }
463            }
464        }
465        if (!p1.hasRoomLocation(getResourceId()))
466            return false;
467        if (!p2.hasRoomLocation(getResourceId()))
468            return false;
469        if (p1.getTimeLocation().hasIntersection(p2.getTimeLocation())) {
470            if (!p1.canShareRooms(p2) || (p1.variable()).maxRoomUse() + (p2.variable()).maxRoomUse() > getCapacity())
471                return true;
472        }
473        return false;
474    }
475
476    @Override
477    public void assigned(Assignment<Lecture, Placement> assignment, long iteration, Placement placement) {
478        if (placement.hasRoomLocation(getResourceId()))
479            super.assigned(assignment, iteration, placement);
480    }
481
482    @Override
483    public void unassigned(Assignment<Lecture, Placement> assignment, long iteration, Placement placement) {
484        if (placement.hasRoomLocation(getResourceId()))
485            super.unassigned(assignment, iteration, placement);
486    }
487
488    /**
489     * Lookup table getResource()[slot] &rarr; lecture using this room placed in the
490     * given time slot (null if empty)
491     * @param assignment current assignment
492     * @param slot time slot
493     * @return list of placements in the room in the given time
494     */
495    public List<Placement> getResource(Assignment<Lecture, Placement> assignment, int slot) {
496        return getContext(assignment).getPlacements(slot);
497    }
498
499    public Placement[] getResourceOfWeek(Assignment<Lecture, Placement> assignment, int startDay) {
500        return getContext(assignment).getResourceOfWeek(startDay);
501    }
502    
503    @Override
504    public String toString() {
505        return "Room " + getName();
506    }
507
508    /** Position of the building 
509     * @param x X-coordinate (latitude)
510     * @param y Y-coordinate (longitude)
511     **/
512    public void setCoordinates(Double x, Double y) {
513        iPosX = x;
514        iPosY = y;
515    }
516
517    /** X-position of the building 
518     * @return X-coordinate (latitude)
519     **/
520    public Double getPosX() {
521        return iPosX;
522    }
523
524    /** Y-position of the building 
525     * @return Y-coordinate (longitude)
526     **/
527    public Double getPosY() {
528        return iPosY;
529    }
530
531    public boolean getIgnoreTooFar() {
532        return iIgnoreTooFar;
533    }
534
535    public boolean getConstraint() {
536        return iConstraint;
537    }
538
539    public Long getType() {
540        return iType;
541    }
542
543    public void setType(Long type) {
544        iType = type;
545    }
546    
547    @Override
548    public RoomConstraintContext createAssignmentContext(Assignment<Lecture, Placement> assignment) {
549        return new RoomConstraintContext(assignment);
550    }
551
552    public class RoomConstraintContext implements AssignmentConstraintContext<Lecture, Placement> {
553        private List<Placement>[] iResource;
554        private int iLastUselessHalfHours = 0;
555        private double iLastBrokenTimePatterns = 0;
556 
557        @SuppressWarnings("unchecked")
558        public RoomConstraintContext(Assignment<Lecture, Placement> assignment) {
559            iResource = new List[Constants.SLOTS_PER_DAY * Constants.NR_DAYS];
560            for (int i = 0; i < iResource.length; i++)
561                iResource[i] = new ArrayList<Placement>(3);
562            for (Lecture lecture: variables()) {
563                Placement placement = assignment.getValue(lecture);
564                if (placement != null && placement.hasRoomLocation(getResourceId())) {
565                    for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
566                        int slot = e.nextElement();
567                        iResource[slot].add(placement);
568                    }
569                }
570            }
571            iLastUselessHalfHours = UselessHalfHours.countUselessSlotsHalfHours(this);
572            getModel().getCriterion(UselessHalfHours.class).inc(assignment, iLastUselessHalfHours);
573            iLastBrokenTimePatterns = BrokenTimePatterns.countUselessSlotsBrokenTimePatterns(this) / 6.0;
574            getModel().getCriterion(BrokenTimePatterns.class).inc(assignment, iLastBrokenTimePatterns);
575        }
576
577        @Override
578        public void assigned(Assignment<Lecture, Placement> assignment, Placement placement) {
579            if (!placement.hasRoomLocation(getResourceId()))
580                return;
581            for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
582                int slot = e.nextElement();
583                iResource[slot].add(placement);
584            }
585            getModel().getCriterion(UselessHalfHours.class).inc(assignment, -iLastUselessHalfHours);
586            iLastUselessHalfHours = UselessHalfHours.countUselessSlotsHalfHours(this);
587            getModel().getCriterion(UselessHalfHours.class).inc(assignment, iLastUselessHalfHours);
588            getModel().getCriterion(BrokenTimePatterns.class).inc(assignment, -iLastBrokenTimePatterns);
589            iLastBrokenTimePatterns = BrokenTimePatterns.countUselessSlotsBrokenTimePatterns(this) / 6.0;
590            getModel().getCriterion(BrokenTimePatterns.class).inc(assignment, iLastBrokenTimePatterns);
591        }
592        
593        @Override
594        public void unassigned(Assignment<Lecture, Placement> assignment, Placement placement) {
595            if (!placement.hasRoomLocation(getResourceId()))
596                return;
597            for (Enumeration<Integer> e = placement.getTimeLocation().getSlots(); e.hasMoreElements();) {
598                int slot = e.nextElement();
599                iResource[slot].remove(placement);
600            }
601            getModel().getCriterion(UselessHalfHours.class).inc(assignment, -iLastUselessHalfHours);
602            iLastUselessHalfHours = UselessHalfHours.countUselessSlotsHalfHours(this);
603            getModel().getCriterion(UselessHalfHours.class).inc(assignment, iLastUselessHalfHours);
604            getModel().getCriterion(BrokenTimePatterns.class).inc(assignment, -iLastBrokenTimePatterns);
605            iLastBrokenTimePatterns = BrokenTimePatterns.countUselessSlotsBrokenTimePatterns(this) / 6.0;
606            getModel().getCriterion(BrokenTimePatterns.class).inc(assignment, iLastBrokenTimePatterns);
607        }
608        
609        public List<Placement> getPlacements(int slot) { return iResource[slot]; }
610        
611        public Placement getPlacement(int slot, int day) {
612            for (Placement p : iResource[slot]) {
613                if (p.getTimeLocation().hasDay(day))
614                    return p;
615            }
616            return null;
617        }
618        
619        public Placement[] getResourceOfWeek(int startDay) {
620            Placement[] ret = new Placement[iResource.length];
621            for (int i = 0; i < iResource.length; i++) {
622                ret[i] = getPlacement(i, startDay + (i / Constants.SLOTS_PER_DAY));
623            }
624            return ret;
625        }
626        
627        public boolean inConflict(Lecture lecture, TimeLocation time) {
628            for (Enumeration<Integer> e = time.getSlots(); e.hasMoreElements();) {
629                int slot = e.nextElement();
630                for (Placement confPlacement : getPlacements(slot)) {
631                    if (!confPlacement.getTimeLocation().shareWeeks(time.getWeekCode())) continue;
632                    if (confPlacement.variable().equals(lecture)) continue;
633                    if (!confPlacement.variable().canShareRoom(lecture)) return true;
634                }
635            }
636            return false;
637        }
638
639    }
640}