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