001    package net.sf.cpsolver.ifs.model;
002    
003    import java.util.*;
004    
005    import net.sf.cpsolver.ifs.util.*;
006    
007    /**
008     * Generic value.
009     * <br><br>
010     * Every value has a notion about the variable it belongs to. It has also a unique id.
011     * By default, every Value has an integer value which is used in general heuristics,
012     * the task is than to minimimize the total value of assigned values in the solution.
013     *
014     * @see Variable
015     * @see Model
016     * @see net.sf.cpsolver.ifs.solver.Solver
017     *
018     * @version
019     * IFS 1.1 (Iterative Forward Search)<br>
020     * Copyright (C) 2006 Tomáš Müller<br>
021     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
022     * Lazenska 391, 76314 Zlin, Czech Republic<br>
023     * <br>
024     * This library is free software; you can redistribute it and/or
025     * modify it under the terms of the GNU Lesser General Public
026     * License as published by the Free Software Foundation; either
027     * version 2.1 of the License, or (at your option) any later version.
028     * <br><br>
029     * This library is distributed in the hope that it will be useful,
030     * but WITHOUT ANY WARRANTY; without even the implied warranty of
031     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
032     * Lesser General Public License for more details.
033     * <br><br>
034     * You should have received a copy of the GNU Lesser General Public
035     * License along with this library; if not, write to the Free Software
036     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
037     */
038    public class Value implements Comparable {
039        private static IdGenerator sIdGenerator = new IdGenerator();
040        
041        private long iId;
042        private Variable iVariable = null;
043        
044        private long iAssignmentCounter = 0;
045        private long iLastAssignmentIteration = -1;
046        private long iLastUnassignmentIteration = -1;
047        
048        /** Integer value */
049        protected double iValue = 0;
050        /** Extra information which can be used by an IFS extension (see {@link net.sf.cpsolver.ifs.extension.Extension})*/
051        private Object iExtra = null;
052        
053        /** Constructor
054         * @param variable variable which the value belongs to
055         */
056        public Value(Variable variable) {
057            iId = sIdGenerator.newId();
058            iVariable = variable;
059        }
060    
061        /** Constructor
062         * @param variable variable which the value belongs to
063         * @param value integer value
064         */
065        public Value(Variable variable, double value) {
066            iId = sIdGenerator.newId();
067            iVariable = variable;
068            iValue = value;
069        }
070        
071        /** Returns the variable which this value belongs to */
072        public Variable variable() { return iVariable; }
073        /** Sets the variable which this value belongs to */
074        public void setVariable(Variable variable) { iVariable = variable; }
075        
076        /** Notification (called by variable) that this value is assigned
077         * @param iteration current iteration
078         */
079        public void assigned(long iteration) {
080            iAssignmentCounter++; iLastAssignmentIteration = iteration;
081        }
082        
083        /** Notification (called by variable) that this value is unassigned
084         * @param iteration current iteration
085         */
086        public void unassigned(long iteration) { iLastUnassignmentIteration = iteration; }
087        
088        /** Returns the iteration when the value was assigned at last (-1 if never).*/
089        public long lastAssignmentIteration() { return iLastAssignmentIteration; }
090        /** Returns the iteration when the value was unassigned at last (-1 if never).*/
091        public long lastUnassignmentIteration() { return iLastUnassignmentIteration; }
092        /** Returns the number of assignments of this value to its variable.*/
093        public long countAssignments() { return iAssignmentCounter; }
094        
095        /** Unique id */
096        public long getId() { return iId;}
097        
098        /** Values name -- for printing purposes (E.g., Monday 7:30)*/
099        public String getName() { return String.valueOf(iId); }
100        
101        /** Values description -- for printing purposes*/
102        public String getDescription() { return null; }
103        
104        /** Dobouble representaion. This allows us to have generic optimization criteria. The task
105         * is than to minimize total value of assigned variables of a solution.
106         */
107        public double toDouble() { return iValue; }
108        
109        public String toString() { return getName(); }
110        
111        public int hashCode() { return (int)iId; }
112        
113        /** Comparison of two values which is based only on the value (not appropriate variable etc.). toDouble() is compared by default. */
114        public boolean valueEquals(Value value) {
115            if (value==null) return false;
116            return toDouble()==value.toDouble();
117        }
118        
119        public int compareTo(Object o) {
120            if (o==null || !(o instanceof Value)) return -1;
121            int cmp = Double.compare(toDouble(),((Value)o).toDouble());
122            if (cmp!=0) return cmp;
123            return Double.compare(getId(),((Value)o).getId());
124        }
125        
126        /** By default, comparison is made on unique ids */
127        public boolean equals(Object o) {
128            try {
129                if (o==null) return false;
130                return getId()==((Value)o).getId();
131            } catch (Exception e) { return false; }
132        }
133        
134        /** Extra information to which can be used by an extension (see {@link net.sf.cpsolver.ifs.extension.Extension}). */
135        public Object getExtra() { return iExtra; }
136        /** Extra information to which can be used by an extension (see {@link net.sf.cpsolver.ifs.extension.Extension}). */
137        public void setExtra(Object object) { iExtra = object; }
138    
139        /** True, if the value is consistent with the given value */
140        public boolean isConsistent(Value value) {
141            for (Enumeration e1=variable().constraints().elements();e1.hasMoreElements();) {
142                    Constraint constraint = (Constraint)e1.nextElement();
143                    if (!constraint.isConsistent(this, value))
144                            return false;
145            }
146            for (Enumeration e1=variable().getModel().globalConstraints().elements();e1.hasMoreElements();) {
147                Constraint constraint = (Constraint)e1.nextElement();
148                if (!constraint.isConsistent(this, value))
149                    return false;
150            }
151            return true;
152        }
153    
154        /** Returns a set of conflicting values with this value. When empty, the value is consistent with the existing assignment. */
155        public java.util.Set conflicts() {
156            HashSet conflicts = new HashSet();
157            for (Enumeration e1=variable().constraints().elements();e1.hasMoreElements();) {
158                Constraint constraint = (Constraint)e1.nextElement();
159                constraint.computeConflicts(this, conflicts);
160            }
161            if (!conflicts.isEmpty()) return conflicts;
162            return null;
163        }
164    }