    001package net.sf.cpsolver.coursett.criteria;
    002
    003import java.util.Collection;
    004import java.util.HashMap;
    005import java.util.HashSet;
    006import java.util.Map;
    007import java.util.Set;
    008
    009import net.sf.cpsolver.coursett.constraint.FlexibleConstraint;
    010import net.sf.cpsolver.coursett.constraint.FlexibleConstraint.FlexibleConstraintType;
    011import net.sf.cpsolver.coursett.model.Lecture;
    012import net.sf.cpsolver.coursett.model.Placement;
    013import net.sf.cpsolver.coursett.model.TimetableModel;
    014import net.sf.cpsolver.ifs.solver.Solver;
    015
    016/**
    017 * The class encapsulates various flexible constraints concerning compact timetables of
    018 * instructors.
    019 *
    020 * <br>
    021 * @version CourseTT 1.2 (University Course Timetabling)<br>
    022 *          Copyright (C) 2012 Matej Lukac<br>
    023 * <br>
    024 *          This library is free software; you can redistribute it and/or modify
    025 *          it under the terms of the GNU Lesser General Public License as
    026 *          published by the Free Software Foundation; either version 3 of the
    027 *          License, or (at your option) any later version. <br>
    028 * <br>
    029 *          This library is distributed in the hope that it will be useful, but
    030 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    031 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    032 *          Lesser General Public License for more details. <br>
    033 * <br>
    034 *          You should have received a copy of the GNU Lesser General Public
    035 *          License along with this library; if not see
    036 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
    037 */
    038public class FlexibleConstraintCriterion extends TimetablingCriterion  {
    039
    040    private boolean iDebug;
    041
    042    public FlexibleConstraintCriterion(){
    043        iValueUpdateType = ValueUpdateType.NoUpdate;
    044    }
    045
    046    @Override
    047    public boolean init(Solver<Lecture, Placement> solver) {
    048        super.init(solver);
    049
    050        iWeight = solver.getProperties().getPropertyDouble("FlexibleConstraint.Weight", 1.0d);
    051        iDebug = solver.getProperties().getPropertyBoolean("FlexibleConstraint.Debug", true);
    052        return true;
    053    }
    054
    055    @Override
    056    public String getPlacementSelectionWeightName() {
    057        return "Placement.FlexibleConstrPreferenceWeight";
    058    }
    059
    060    @Override
    061    public void getInfo(Map<String, String> info) {
    062        TimetableModel m = (TimetableModel)getModel();
    063        if (m.getFlexibleConstraints().isEmpty()) return;
    064
    065        for (FlexibleConstraintType type: FlexibleConstraintType.values()) {
    066            StringBuilder debug = null;
    067            int violated = 0, constraints = 0;
    068
    069            for (FlexibleConstraint c : m.getFlexibleConstraints()) {
    070                if (type.equals(c.getType())) {
    071                    constraints ++;
    072                    if (!c.isConsistent(null, null)) {
    073                        violated++;
    074                        if (iDebug) {
    075                            if (debug == null)
    076                                debug = new StringBuilder(c.getOwner() + " (" + sDoubleFormat.format(c.getNrViolations(new HashSet<Placement>(), null)) + ")");
    077                            else
    078                                debug.append("; " + c.getOwner() + " (" + sDoubleFormat.format(c.getNrViolations(new HashSet<Placement>(), null)) + ")");
    079                        }
    080                    }
    081                }
    082            }
    083
    084            if (constraints > 0) {
    085                info.put(type.getName() + " Constraints", getPerc(violated, 0, constraints) + "% (" + violated + ")");
    086                if (iDebug && violated > 0) info.put(type.getName() + " Violations", debug.toString());
    087            }
    088        }
    089    }
    090
    091    @Override
    092    public void getInfo(Map<String, String> info, Collection<Lecture> variables) {
    093        for (FlexibleConstraintType type: FlexibleConstraintType.values()) {
    094
    095            Set<FlexibleConstraint> constraints = new HashSet<FlexibleConstraint>();
    096            for (Lecture lecture : variables) {
    097                for (FlexibleConstraint c : lecture.getFlexibleGroupConstraints()) {
    098                    if (type.equals(c.getType())) constraints.add(c);
    099                }
    100            }
    101
    102            if (!constraints.isEmpty()) {
    103                int violated = 0;
    104                StringBuilder debug = null;
    105                for (FlexibleConstraint c : constraints) {
    106                    if (!c.isConsistent(null, null)) {
    107                        violated++;
    108                        if (iDebug) {
    109                            if (debug == null)
    110                                debug = new StringBuilder(c.getOwner());
    111                            else
    112                                debug.append("; " + c.getOwner());
    113                        }
    114                    }
    115                }
    116                info.put(type.getName() + " Constraints", getPerc(violated, 0, constraints.size()) + "% (" + violated + ")");
    117                if (iDebug && violated > 0) info.put(type.getName() + " Violations", debug.toString());
    118            }
    119        }
    120    }
    121
    122    @Override
    123    public double getValue(Collection<Lecture> variables) {
    124        Set<FlexibleConstraint> flexibleConstraints = new HashSet<FlexibleConstraint>();
    125        for (Lecture lecture: variables){
    126            flexibleConstraints.addAll(lecture.getFlexibleGroupConstraints());
    127        }
    128        int ret = 0;
    129        for (FlexibleConstraint gc: flexibleConstraints){
    130            ret += gc.getCurrentPreference(null, null);
    131        }
    132        return ret;
    133    }
    134
    135    @Override
    136    public double getValue(Placement value, Set<Placement> conflicts) {
    137        HashMap<Lecture, Placement> assignments = new HashMap<Lecture, Placement>();
    138        assignments.put(value.variable(), value);
    139
    140        double ret = 0.0;
    141        for (FlexibleConstraint gc : value.variable().getFlexibleGroupConstraints())
    142            ret += gc.getCurrentPreference(conflicts, assignments);
    143
    144        assignments.put(value.variable(), null);
    145        for (FlexibleConstraint gc : value.variable().getFlexibleGroupConstraints())
    146            ret -= gc.getCurrentPreference(conflicts, assignments);
    147
    148        return ret;
    149    }
    150}