    001package org.cpsolver.coursett.criteria;
    002
    003import java.util.Collection;
    004import java.util.Set;
    005
    006import org.cpsolver.coursett.Constants;
    007import org.cpsolver.coursett.model.Lecture;
    008import org.cpsolver.coursett.model.Placement;
    009import org.cpsolver.coursett.model.RoomLocation;
    010import org.cpsolver.coursett.preference.PreferenceCombination;
    011import org.cpsolver.ifs.assignment.Assignment;
    012import org.cpsolver.ifs.util.DataProperties;
    013
    014
    015/**
    016 * Too big rooms. This criterion counts cases where a class is placed in a room
    017 * that is too big for the class. In general, a room is discouraged (in this
    018 * criterion) if it has 25% more space than needed, strongly discouraged
    019 * if it has more than 50% space than needed. Needed space is counted as the space
    020 * of the smallest room in which a class can take place.
    021 * <br>
    022 *
    023 * @author  Tomáš Müller
    024 * @version CourseTT 1.3 (University Course Timetabling)<br>
    025 *          Copyright (C) 2006 - 2014 Tomáš Müller<br>
    026 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
    027 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
    028 * <br>
    029 *          This library is free software; you can redistribute it and/or modify
    030 *          it under the terms of the GNU Lesser General Public License as
    031 *          published by the Free Software Foundation; either version 3 of the
    032 *          License, or (at your option) any later version. <br>
    033 * <br>
    034 *          This library is distributed in the hope that it will be useful, but
    035 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    036 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    037 *          Lesser General Public License for more details. <br>
    038 * <br>
    039 *          You should have received a copy of the GNU Lesser General Public
    040 *          License along with this library; if not see
    041 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
    042 */
    043public class TooBigRooms extends TimetablingCriterion {
    044    private double iDiscouragedRoomSize, iStronglyDiscouragedRoomSize;
    045
    046    @Override
    047    public void configure(DataProperties properties) {
    048        super.configure(properties);
    049        iDiscouragedRoomSize = properties.getPropertyDouble("TooBigRooms.DiscouragedRoomSize", 1.25);
    050        iStronglyDiscouragedRoomSize = properties.getPropertyDouble("TooBigRooms.StronglyDiscouragedRoomSize", 1.5);
    051    }
    052
    053    @Override
    054    public double getWeightDefault(DataProperties config) {
    055        return config.getPropertyDouble("Comparator.TooBigRoomWeight", 0.1);
    056    }
    057
    058    @Override
    059    public String getPlacementSelectionWeightName() {
    060        return "Placement.TooBigRoomWeight";
    061    }
    062
    063    @Override
    064    public double getValue(Assignment<Lecture, Placement> assignment, Placement value, Set<Placement> conflicts) {
    065        double ret = getPreference(value);
    066        if (conflicts != null)
    067            for (Placement conflict: conflicts)
    068                ret -= getPreference(conflict);
    069        return ret;
    070    }
    071
    072    @Override
    073    public double[] getBounds(Assignment<Lecture, Placement> assignment, Collection<Lecture> variables) {
    074        double[] bounds = new double[] { 0.0, 0.0 };
    075        for (Lecture lect: variables) {
    076            if (lect.getNrRooms() > 0)
    077                bounds[0] += Constants.sPreferenceLevelStronglyDiscouraged;
    078        }
    079        return bounds;
    080    }
    081
    082    private long getDiscouragedRoomSize(Placement value) {
    083        return Math.round(iDiscouragedRoomSize * value.variable().minRoomSize());
    084    }
    085
    086    private long getStronglyDiscouragedRoomSize(Placement value) {
    087        return Math.round(iStronglyDiscouragedRoomSize * value.variable().minRoomSize());
    088    }
    089
    090    public int getPreference(Placement value) {
    091        if (value.isMultiRoom()) {
    092            PreferenceCombination pref = PreferenceCombination.getDefault();
    093            for (RoomLocation r : value.getRoomLocations()) {
    094                if (r.getRoomSize() > getStronglyDiscouragedRoomSize(value))
    095                    pref.addPreferenceInt(Constants.sPreferenceLevelStronglyDiscouraged);
    096                else if (r.getRoomSize() > getDiscouragedRoomSize(value))
    097                    pref.addPreferenceInt(Constants.sPreferenceLevelDiscouraged);
    098            }
    099            return pref.getPreferenceInt();
    100        } else {
    101            if (value.getRoomLocation().getRoomSize() > getStronglyDiscouragedRoomSize(value))
    102                return Constants.sPreferenceLevelStronglyDiscouraged;
    103            else if (value.getRoomLocation().getRoomSize() > getDiscouragedRoomSize(value))
    104                return Constants.sPreferenceLevelDiscouraged;
    105            else
    106                return Constants.sPreferenceLevelNeutral;
    107        }
    108    }
    109
    110    /** Use {@link TooBigRooms#getPreference(Placement)} instead. */
    111    @Deprecated
    112    public static int getTooBigRoomPreference(Placement value) {
    113        if (value.isMultiRoom()) {
    114            PreferenceCombination pref = PreferenceCombination.getDefault();
    115            for (RoomLocation r : value.getRoomLocations()) {
    116                if (r.getRoomSize() > Math.round(1.50 * value.variable().minRoomSize()))
    117                    pref.addPreferenceInt(Constants.sPreferenceLevelStronglyDiscouraged);
    118                else if (r.getRoomSize() > Math.round(1.25 * value.variable().minRoomSize()))
    119                    pref.addPreferenceInt(Constants.sPreferenceLevelDiscouraged);
    120            }
    121            return pref.getPreferenceInt();
    122        } else {
    123            if (value.getRoomLocation().getRoomSize() > Math.round(1.50 * value.variable().minRoomSize()))
    124                return Constants.sPreferenceLevelStronglyDiscouraged;
    125            else if (value.getRoomLocation().getRoomSize() > Math.round(1.25 * value.variable().minRoomSize()))
    126                return Constants.sPreferenceLevelDiscouraged;
    127            else
    128                return Constants.sPreferenceLevelNeutral;
    129        }
    130    }
    131}