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}