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