001package net.sf.cpsolver.coursett.constraint; 002 003import java.util.Set; 004 005import net.sf.cpsolver.coursett.model.Lecture; 006import net.sf.cpsolver.coursett.model.Placement; 007import net.sf.cpsolver.coursett.model.RoomSharingModel; 008import net.sf.cpsolver.ifs.model.WeakeningConstraint; 009import 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 Tomáš Müller<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 */ 035public 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}