001 package net.sf.cpsolver.ifs.model;
002
003 import java.util.HashSet;
004 import java.util.Set;
005
006 import 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 Tomas Muller<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 */
039 public 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 }