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