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}