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