001package org.cpsolver.ifs.model; 002 003import java.util.HashSet; 004import java.util.Set; 005 006import org.cpsolver.ifs.assignment.Assignment; 007import org.cpsolver.ifs.assignment.AssignmentComparable; 008import org.cpsolver.ifs.assignment.ValueComparator; 009import org.cpsolver.ifs.assignment.context.ExtensionWithContext; 010import org.cpsolver.ifs.criteria.Criterion; 011import org.cpsolver.ifs.util.IdGenerator; 012 013 014/** 015 * Generic value. <br> 016 * <br> 017 * Every value has a notion about the variable it belongs to. It has also a 018 * unique id. By default, every Value has an integer value which is used in 019 * general heuristics, the task is than to minimimize the total value of 020 * assigned values in the solution. 021 * 022 * @see Variable 023 * @see Model 024 * @see org.cpsolver.ifs.solver.Solver 025 * 026 * @author Tomáš Müller 027 * @version IFS 1.3 (Iterative Forward Search)<br> 028 * Copyright (C) 2006 - 2014 Tomáš Müller<br> 029 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 030 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 031 * <br> 032 * This library is free software; you can redistribute it and/or modify 033 * it under the terms of the GNU Lesser General Public License as 034 * published by the Free Software Foundation; either version 3 of the 035 * License, or (at your option) any later version. <br> 036 * <br> 037 * This library is distributed in the hope that it will be useful, but 038 * WITHOUT ANY WARRANTY; without even the implied warranty of 039 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 040 * Lesser General Public License for more details. <br> 041 * <br> 042 * You should have received a copy of the GNU Lesser General Public 043 * License along with this library; if not see 044 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 045 * 046 * @param <V> Variable 047 * @param <T> Value 048 */ 049public class Value<V extends Variable<V, T>, T extends Value<V, T>> implements Comparable<T>, AssignmentComparable<T, V, T> { 050 private static IdGenerator sIdGenerator = new IdGenerator(); 051 052 private long iId; 053 private V iVariable = null; 054 055 /** Integer value */ 056 protected Double iValue = null; 057 /** 058 * Extra information which can be used by an IFS extension (see 059 * {@link org.cpsolver.ifs.extension.Extension}) 060 */ 061 private Object iExtra = null; 062 063 /** 064 * Constructor 065 * 066 * @param variable 067 * variable which the value belongs to 068 */ 069 public Value(V variable) { 070 iId = sIdGenerator.newId(); 071 iVariable = variable; 072 } 073 074 /** 075 * Constructor 076 * 077 * @param variable 078 * variable which the value belongs to 079 * @param value 080 * integer value 081 */ 082 public Value(V variable, Double value) { 083 iId = sIdGenerator.newId(); 084 iVariable = variable; 085 iValue = value; 086 } 087 088 /** Returns the variable which this value belongs to 089 * @return variable of this value 090 **/ 091 public V variable() { 092 return iVariable; 093 } 094 095 /** Sets the variable which this value belongs to 096 * @param variable variable of this value 097 **/ 098 @SuppressWarnings({ "unchecked", "rawtypes" }) 099 public void setVariable(Variable variable) { 100 iVariable = (V) variable; 101 } 102 103 /** Unique id 104 * @return value id 105 **/ 106 public long getId() { 107 return iId; 108 } 109 110 /** Values name -- for printing purposes (E.g., Monday 7:30) 111 * @return value name 112 **/ 113 public String getName() { 114 return String.valueOf(iId); 115 } 116 117 /** Values description -- for printing purposes 118 * @return value description 119 **/ 120 public String getDescription() { 121 return null; 122 } 123 124 /** 125 * Double representation. This allows us to have generic optimization 126 * criteria. The task is than to minimize total value of assigned variables 127 * of a solution. 128 * @param assignment current assignment 129 * @return this value's contribution to the solution value 130 */ 131 @SuppressWarnings("unchecked") 132 public double toDouble(Assignment<V, T> assignment) { 133 if (iValue != null) 134 return iValue; 135 double ret = 0.0; 136 for (Criterion<V, T> criterion: variable().getModel().getCriteria()) 137 ret += criterion.getWeightedValue(assignment, (T)this, null); 138 return ret; 139 } 140 141 /** 142 * Double representation. This allows us to have generic optimization 143 * criteria. The task is than to minimize total value of assigned variables 144 * of a solution. 145 * If the value may depend on other values of the assignment, use {@link Value#toDouble(Assignment)} instead. 146 * @return this value's contribution to the solution value 147 */ 148 @Deprecated 149 public double toDouble() { 150 return toDouble(variable().getModel().getDefaultAssignment()); 151 } 152 153 @Override 154 public String toString() { 155 return getName(); 156 } 157 158 @Override 159 public int hashCode() { 160 return (int) iId; 161 } 162 163 /** 164 * Comparison of two values which is based only on the value (not 165 * appropriate variable etc.). {@link Value#toDouble(Assignment)} is compared by default. 166 * @param assignment current assignment 167 * @param value a value 168 * @return true if the two values have the same impact on the solution value 169 */ 170 public boolean valueEquals(Assignment<V, T> assignment, T value) { 171 if (value == null) 172 return false; 173 return toDouble(assignment) == value.toDouble(assignment); 174 } 175 176 /** 177 * Comparison of two values which is based only on the value (not 178 * appropriate variable etc.). {@link Value#toDouble(Assignment)} is compared by default. 179 * Use {@link Value#valueEquals(Assignment, Value)} instead. 180 * @param value a value 181 * @return true if the two values have the same impact on the solution value 182 */ 183 @Deprecated 184 public boolean valueEquals(T value) { 185 return valueEquals(variable().getModel().getDefaultAssignment(), value); 186 } 187 188 /** 189 * Compare two values by their value 190 */ 191 @Override 192 public int compareTo(Assignment<V, T> assignment, T value) { 193 if (value == null) 194 return -1; 195 int cmp = Double.compare(toDouble(assignment), value.toDouble(assignment)); 196 if (cmp != 0) 197 return cmp; 198 return Double.compare(getId(), value.getId()); 199 } 200 201 /** 202 * Compare two values by their value. 203 * Use {@link Value#compareTo(Assignment, Value)} and {@link ValueComparator} instead. 204 */ 205 @Override 206 @Deprecated 207 public int compareTo(T value) { 208 return compareTo(variable().getModel().getDefaultAssignment(), value); 209 } 210 211 /** By default, comparison is made on unique ids */ 212 @Override 213 public boolean equals(Object o) { 214 if (o == null || !(o instanceof Value<?, ?>)) 215 return false; 216 return getId() == ((Value<?, ?>) o).getId(); 217 } 218 219 /** 220 * Extra information to which can be used by an extension (see 221 * {@link org.cpsolver.ifs.extension.Extension}). 222 * Use {@link ExtensionWithContext} instead. 223 * @return extra object 224 */ 225 @Deprecated 226 public Object getExtra() { 227 return iExtra; 228 } 229 230 /** 231 * Extra information to which can be used by an extension (see 232 * {@link org.cpsolver.ifs.extension.Extension}). 233 * Use {@link ExtensionWithContext} instead. 234 * @param object extra object 235 */ 236 @Deprecated 237 public void setExtra(Object object) { 238 iExtra = object; 239 } 240 241 /** True, if the value is consistent with the given value 242 * @param value another value (of a different variable) 243 * @return true if the other value is consistent with this value (there is no hard constraint which would return {@link Constraint#isConsistent(Value, Value)} false) 244 **/ 245 @SuppressWarnings("unchecked") 246 public boolean isConsistent(T value) { 247 for (Constraint<V, T> constraint : iVariable.constraints()) { 248 if (!constraint.isConsistent((T) this, value)) 249 return false; 250 } 251 for (Constraint<V, T> constraint : iVariable.getModel().globalConstraints()) { 252 if (!constraint.isConsistent((T) this, value)) 253 return false; 254 } 255 return true; 256 } 257 258 /** 259 * Returns a set of conflicting values with this value. When empty, the 260 * value is consistent with the existing assignment. 261 * @param assignment current assignment 262 * @return set of conflicting values 263 */ 264 @SuppressWarnings("unchecked") 265 public Set<T> conflicts(Assignment<V, T> assignment) { 266 HashSet<T> conflicts = new HashSet<T>(); 267 for (Constraint<V, T> constraint : iVariable.constraints()) { 268 constraint.computeConflicts(assignment, (T) this, conflicts); 269 } 270 for (Constraint<V, T> constraint : iVariable.getModel().globalConstraints()) { 271 constraint.computeConflicts(assignment, (T) this, conflicts); 272 } 273 if (!conflicts.isEmpty()) 274 return conflicts; 275 return null; 276 } 277 278 /** 279 * Returns a set of conflicting values with this value. When empty, the 280 * value is consistent with the existing assignment. 281 * Use {@link Value#conflicts(Assignment)} instead. 282 * @return set of conflicting values 283 */ 284 @Deprecated 285 public Set<T> conflicts() { 286 return conflicts(variable().getModel().getDefaultAssignment()); 287 } 288}