001 package net.sf.cpsolver.exam.criteria; 002 003 import java.util.Set; 004 005 import net.sf.cpsolver.exam.model.ExamDistributionConstraint; 006 import net.sf.cpsolver.exam.model.ExamModel; 007 import net.sf.cpsolver.exam.model.ExamPlacement; 008 import net.sf.cpsolver.ifs.util.DataProperties; 009 010 /** 011 * Distribution penalty. I.e., sum weights of violated distribution 012 * constraints. 013 * <br><br> 014 * A weight of violated distribution soft constraints (see 015 * {@link ExamDistributionConstraint}) can be set by problem property 016 * Exams.RoomDistributionWeight, or in the input xml file, property 017 * roomDistributionWeight. 018 * 019 * <br> 020 * 021 * @version ExamTT 1.2 (Examination Timetabling)<br> 022 * Copyright (C) 2008 - 2012 Tomas Muller<br> 023 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 024 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 025 * <br> 026 * This library is free software; you can redistribute it and/or modify 027 * it under the terms of the GNU Lesser General Public License as 028 * published by the Free Software Foundation; either version 3 of the 029 * License, or (at your option) any later version. <br> 030 * <br> 031 * This library is distributed in the hope that it will be useful, but 032 * WITHOUT ANY WARRANTY; without even the implied warranty of 033 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 034 * Lesser General Public License for more details. <br> 035 * <br> 036 * You should have received a copy of the GNU Lesser General Public 037 * License along with this library; if not see 038 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 039 */ 040 public class DistributionPenalty extends ExamCriterion { 041 042 public DistributionPenalty() { 043 iValueUpdateType = ValueUpdateType.NoUpdate; 044 } 045 046 @Override 047 public String getWeightName() { 048 return "Exams.DistributionWeight"; 049 } 050 051 @Override 052 public String getXmlWeightName() { 053 return "distributionWeight"; 054 } 055 056 @Override 057 public double getWeightDefault(DataProperties config) { 058 return 1.0; 059 } 060 061 @Override 062 public double getValue(ExamPlacement value, Set<ExamPlacement> conflicts) { 063 int penalty = 0; 064 for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) { 065 if (dc.isHard()) 066 continue; 067 boolean sat = dc.isSatisfied(value); 068 if (sat != dc.isSatisfied()) 069 penalty += (sat ? -dc.getWeight() : dc.getWeight()); 070 } 071 return penalty; 072 } 073 074 @Override 075 public boolean isRoomCriterion() { return true; } 076 077 /** 078 * Room related distribution penalty, i.e., sum weights of violated 079 * distribution constraints 080 */ 081 @Override 082 public double getRoomValue(ExamPlacement value) { 083 int penalty = 0; 084 for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) { 085 if (dc.isHard() || !dc.isRoomRelated()) 086 continue; 087 boolean sat = dc.isSatisfied(value); 088 if (sat != dc.isSatisfied()) 089 penalty += (sat ? -dc.getWeight() : dc.getWeight()); 090 } 091 return penalty; 092 } 093 094 095 @Override 096 public boolean isPeriodCriterion() { return true; } 097 098 /** 099 * Period related distribution penalty, i.e., sum weights of violated 100 * distribution constraints 101 */ 102 @Override 103 public double getPeriodValue(ExamPlacement value) { 104 int penalty = 0; 105 for (ExamDistributionConstraint dc : value.variable().getDistributionConstraints()) { 106 if (dc.isHard() || !dc.isPeriodRelated()) 107 continue; 108 boolean sat = dc.isSatisfied(value); 109 if (sat != dc.isSatisfied()) 110 penalty += (sat ? -dc.getWeight() : dc.getWeight()); 111 } 112 return penalty; 113 } 114 115 @Override 116 protected void computeBounds() { 117 iBounds = new double[] { 0.0, 0.0 }; 118 for (ExamDistributionConstraint dc : ((ExamModel)getModel()).getDistributionConstraints()) { 119 if (dc.isHard()) 120 continue; 121 iBounds[1] += dc.getWeight(); 122 } 123 } 124 125 @Override 126 public String toString() { 127 return "DP:" + sDoubleFormat.format(getWeightedValue()); 128 } 129 }