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    }