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