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.Value;
009    import net.sf.cpsolver.ifs.util.DataProperties;
010    
011    /**
012     * Discouraged room constraint. 
013     * This constraint is based on {@link RoomConstraint}, however, it tries to minimize the usage of the room as much as possible.  
014     * 
015     * @version
016     * CourseTT 1.1 (University Course Timetabling)<br>
017     * Copyright (C) 2006 Tomáš Müller<br>
018     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
019     * Lazenska 391, 76314 Zlin, Czech Republic<br>
020     * <br>
021     * This library is free software; you can redistribute it and/or
022     * modify it under the terms of the GNU Lesser General Public
023     * License as published by the Free Software Foundation; either
024     * version 2.1 of the License, or (at your option) any later version.
025     * <br><br>
026     * This library is distributed in the hope that it will be useful,
027     * but 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.
030     * <br><br>
031     * You should have received a copy of the GNU Lesser General Public
032     * License along with this library; if not, write to the Free Software
033     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
034     */
035    public class DiscouragedRoomConstraint extends RoomConstraint {
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, RoomSharingModel roomSharingModel, int x, int 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        public int getUsage() {
052            return iUsage;
053        }
054        
055        public boolean isOverLimit(Value value) {
056            if (!iEnabled) return false; //not enabled
057            if (iUnassignmentsToWeaken==0) return false; //not working
058                    Placement placement = (Placement) value;
059                    if (!placement.hasRoomLocation(getResourceId())) return false; //different room
060                    Lecture lecture = (Lecture)placement.variable();
061                    if (lecture.roomLocations().size()==lecture.getNrRooms()) return false; //required room
062                    if (lecture.isCommitted()) return false; //commited class
063                    if (lecture.getAssignment()!=null && ((Placement)lecture.getAssignment()).hasRoomLocation(getResourceId())) return false; //already assigned in this room
064                    if (iUsage+1<=iLimit) return false; //under the limit
065            return true;
066        }
067        
068        public void computeConflicts(Value value, Set conflicts) {
069            if (!getConstraint()) return;
070            super.computeConflicts(value, conflicts);
071            if (isOverLimit(value)) conflicts.add(value);
072        }
073        
074        public boolean inConflict(Value value) {
075            if (!getConstraint()) return false;
076            if (isOverLimit(value)) return true;
077            return super.inConflict(value);
078        }
079        
080        public boolean isConsistent(Value value1, Value value2) {
081            if (!getConstraint()) return true;
082            if (isOverLimit(value1) || isOverLimit(value2)) return false;
083            return super.isConsistent(value1, value2);
084        }
085        
086        public void assigned(long iteration, Value value) {
087            super.assigned(iteration, value);
088            Placement placement = (Placement) value;
089            if (!placement.hasRoomLocation(getResourceId())) return;
090            Lecture lecture = (Lecture)placement.variable();
091                    if (lecture.isCommitted()) return;
092            iUsage++;
093        }
094        
095        public void unassigned(long iteration, Value value) {
096            super.unassigned(iteration, value);
097            Placement placement = (Placement) value;
098            if (!placement.hasRoomLocation(getResourceId())) {
099                    iUnassignment++;
100                    if (iUnassignmentsToWeaken>0 && iUnassignment%iUnassignmentsToWeaken==0) iLimit++;
101            } else {
102                    iUsage--;
103            }
104        }
105        
106        public String getName() { return "discouraged "+super.getName(); }
107        public String toString() { return "Discouraged "+super.toString(); }
108        
109        public void setEnabled(boolean enabled) { 
110            iEnabled = enabled;
111            iLimit = Math.max(iUsage, iLimit);
112        }
113        public boolean isEnabled() { return iEnabled; }
114    }