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 }