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 152 @Override 153 public void weaken(Placement value) { 154 while (isOverLimit(value)) iLimit ++; 155 } 156 }