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