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