001    package net.sf.cpsolver.coursett.constraint;
002    
003    import java.util.Set;
004    
005    import net.sf.cpsolver.coursett.model.Lecture;
006    import net.sf.cpsolver.coursett.model.Placement;
007    import net.sf.cpsolver.coursett.model.RoomSharingModel;
008    import net.sf.cpsolver.ifs.util.DataProperties;
009    
010    /**
011     * Discouraged room constraint. This constraint is based on
012     * {@link RoomConstraint}, however, it tries to minimize the usage of the room
013     * as much as possible.
014     * 
015     * @version CourseTT 1.2 (University Course Timetabling)<br>
016     *          Copyright (C) 2006 - 2010 Tomas Muller<br>
017     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
018     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
019     * <br>
020     *          This library is free software; you can redistribute it and/or modify
021     *          it under the terms of the GNU Lesser General Public License as
022     *          published by the Free Software Foundation; either version 3 of the
023     *          License, or (at your option) any later version. <br>
024     * <br>
025     *          This library is distributed in the hope that it will be useful, but
026     *          WITHOUT ANY WARRANTY; without even the implied warranty of
027     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
028     *          Lesser General Public License for more details. <br>
029     * <br>
030     *          You should have received a copy of the GNU Lesser General Public
031     *          License along with this library; if not see
032     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
033     */
034    public class DiscouragedRoomConstraint extends RoomConstraint implements WeakeningConstraint {
035        int iUsage = 0;
036        int iLimit = 0;
037        boolean iEnabled = false;
038    
039        private int iUnassignmentsToWeaken = 1000;
040        private long iUnassignment = 0;
041    
042        public DiscouragedRoomConstraint(DataProperties config, Long id, String name, Long buildingId, int capacity,
043                RoomSharingModel roomSharingModel, Double x, Double y, boolean ignoreTooFar, boolean constraint) {
044            super(id, name, buildingId, capacity, roomSharingModel, x, y, ignoreTooFar, constraint);
045            iUnassignmentsToWeaken = config.getPropertyInt("DiscouragedRoom.Unassignments2Weaken", iUnassignmentsToWeaken);
046        }
047    
048        public int getLimit() {
049            return iLimit;
050        }
051    
052        public int getUsage() {
053            return iUsage;
054        }
055    
056        public boolean isOverLimit(Placement value) {
057            if (!iEnabled)
058                return false; // not enabled
059            if (iUnassignmentsToWeaken == 0)
060                return false; // not working
061            Placement placement = value;
062            if (!placement.hasRoomLocation(getResourceId()))
063                return false; // different room
064            Lecture lecture = placement.variable();
065            if (lecture.roomLocations().size() == lecture.getNrRooms())
066                return false; // required room
067            if (lecture.isCommitted())
068                return false; // commited class
069            if (lecture.getAssignment() != null && (lecture.getAssignment()).hasRoomLocation(getResourceId()))
070                return false; // already assigned in this room
071            if (iUsage + 1 <= iLimit)
072                return false; // under the limit
073            return true;
074        }
075    
076        @Override
077        public void computeConflicts(Placement value, Set<Placement> conflicts) {
078            if (!getConstraint())
079                return;
080            super.computeConflicts(value, conflicts);
081            if (isOverLimit(value))
082                conflicts.add(value);
083        }
084    
085        @Override
086        public boolean inConflict(Placement value) {
087            if (!getConstraint())
088                return false;
089            if (isOverLimit(value))
090                return true;
091            return super.inConflict(value);
092        }
093    
094        @Override
095        public boolean isConsistent(Placement value1, Placement value2) {
096            if (!getConstraint())
097                return true;
098            if (isOverLimit(value1) || isOverLimit(value2))
099                return false;
100            return super.isConsistent(value1, value2);
101        }
102    
103        @Override
104        public void assigned(long iteration, Placement value) {
105            super.assigned(iteration, value);
106            Placement placement = value;
107            if (!placement.hasRoomLocation(getResourceId()))
108                return;
109            Lecture lecture = placement.variable();
110            if (lecture.isCommitted())
111                return;
112            iUsage++;
113        }
114    
115        @Override
116        public void unassigned(long iteration, Placement value) {
117            super.unassigned(iteration, value);
118            Placement placement = value;
119            if (!placement.hasRoomLocation(getResourceId())) {
120                iUnassignment++;
121                if (iUnassignmentsToWeaken > 0 && iUnassignment % iUnassignmentsToWeaken == 0)
122                    iLimit++;
123            } else {
124                iUsage--;
125            }
126        }
127    
128        @Override
129        public String getName() {
130            return "discouraged " + super.getName();
131        }
132    
133        @Override
134        public String toString() {
135            return "Discouraged " + super.toString();
136        }
137    
138        public void setEnabled(boolean enabled) {
139            iEnabled = enabled;
140            iLimit = Math.max(iUsage, iLimit);
141        }
142    
143        public boolean isEnabled() {
144            return iEnabled;
145        }
146    
147        @Override
148        public void weaken() {
149            iLimit ++;
150        }
151    }