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