001package net.sf.cpsolver.exam.criteria.additional;
002
003import java.util.Set;
004
005import net.sf.cpsolver.exam.criteria.ExamCriterion;
006import net.sf.cpsolver.exam.model.ExamDistributionConstraint;
007import net.sf.cpsolver.exam.model.ExamModel;
008import net.sf.cpsolver.exam.model.ExamPlacement;
009
010/**
011 * Experimental criterion counting violations of hard distribution constraints.
012 * <br><br>
013 * To enable breaking of hard distribution constraints, set parameter Exam.SoftDistributions to
014 * a weight that should be inferred by a hard distribution constraint being broken.
015 * 
016 * <br>
017 * 
018 * @version ExamTT 1.2 (Examination Timetabling)<br>
019 *          Copyright (C) 2008 - 2012 Tomáš Müller<br>
020 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
021 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
022 * <br>
023 *          This library is free software; you can redistribute it and/or modify
024 *          it under the terms of the GNU Lesser General Public License as
025 *          published by the Free Software Foundation; either version 3 of the
026 *          License, or (at your option) any later version. <br>
027 * <br>
028 *          This library is distributed in the hope that it will be useful, but
029 *          WITHOUT ANY WARRANTY; without even the implied warranty of
030 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
031 *          Lesser General Public License for more details. <br>
032 * <br>
033 *          You should have received a copy of the GNU Lesser General Public
034 *          License along with this library; if not see
035 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
036 */
037public class DistributionViolation extends ExamCriterion {
038
039    @Override
040    public String getWeightName() {
041        return "Exam.SoftDistributions";
042    }
043    
044    @Override
045    public String getXmlWeightName() {
046        return "softDistributions";
047    }
048
049    @Override
050    public double getValue(ExamPlacement value, Set<ExamPlacement> conflicts) {
051        int penalty = 0;
052        for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) {
053            if (dc.isHard() || getWeight() != dc.getWeight())
054                continue;
055            boolean sat = dc.isSatisfied(value);
056            if (sat != dc.isSatisfied())
057                penalty += (sat ? -1.0 : 1.0);
058        }
059        return penalty;
060    }
061    
062    @Override
063    protected double[] computeBounds() {
064        double[] bounds = new double[] { 0.0, 0.0 };
065        for (ExamDistributionConstraint dc : ((ExamModel)getModel()).getDistributionConstraints()) {
066            if (!dc.isHard() && getWeight() == dc.getWeight())
067                bounds[1] ++;
068        }
069        return bounds;
070    }
071    
072    @Override
073    public boolean isRoomCriterion() { return true; }
074    
075    @Override
076    public double getRoomValue(ExamPlacement value) {
077        int penalty = 0;
078        for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) {
079            if (dc.isHard() || getWeight() != dc.getWeight() || !dc.isRoomRelated())
080                continue;
081            boolean sat = dc.isSatisfied(value);
082            if (sat != dc.isSatisfied())
083                penalty += (sat ? -1.0 : 1.0);
084        }
085        return penalty;
086    }
087
088    @Override
089    public boolean isPeriodCriterion() { return true; }
090    
091    @Override
092    public double getPeriodValue(ExamPlacement value) {
093        int penalty = 0;
094        for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) {
095            if (dc.isHard() || getWeight() != dc.getWeight() || !dc.isPeriodRelated())
096                continue;
097            boolean sat = dc.isSatisfied(value);
098            if (sat != dc.isSatisfied())
099                penalty += (sat ? -1.0 : 1.0);
100        }
101        return penalty;
102    }
103
104    @Override
105    public String toString() {
106        return (getValue() <= 0.0 ? "" : "!D:" + sDoubleFormat.format(getValue()));
107    }
108}