    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}