001    package net.sf.cpsolver.ifs.extension;
002    
003    import net.sf.cpsolver.ifs.model.Constraint;
004    import net.sf.cpsolver.ifs.model.Value;
005    
006    /**
007     * This class describing an assignment of a value to a variable together with a counter (used by CBS).
008     *
009     * Counter also supports ageing: the counter is multiplied by aging factor for each iteration.
010     *
011     * @version
012     * IFS 1.1 (Iterative Forward Search)<br>
013     * Copyright (C) 2006 Tomáš Müller<br>
014     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
015     * Lazenska 391, 76314 Zlin, Czech Republic<br>
016     * <br>
017     * This library is free software; you can redistribute it and/or
018     * modify it under the terms of the GNU Lesser General Public
019     * License as published by the Free Software Foundation; either
020     * version 2.1 of the License, or (at your option) any later version.
021     * <br><br>
022     * This library is distributed in the hope that it will be useful,
023     * but WITHOUT ANY WARRANTY; without even the implied warranty of
024     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
025     * Lesser General Public License for more details.
026     * <br><br>
027     * You should have received a copy of the GNU Lesser General Public
028     * License along with this library; if not, write to the Free Software
029     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
030     */
031    public class Assignment {
032        private Value iValue;
033        private double iCounter = 1.0;
034        private long iLastRevision;
035        private double iAgeing = 1.0;
036        private Constraint iConstraint = null;
037        
038        /** Constructor
039         * @param iteration current iteration
040         * @param value value
041         * @param ageing ageing factor
042         */
043        public Assignment(long iteration, Value value, double ageing) {
044            iValue = value;
045            iLastRevision = iteration;
046            iAgeing = ageing;
047        }
048        
049        /** Returns value */
050        public Value getValue() {
051            return iValue;
052        }
053        
054        /** Increments counter
055         * @param iteration current iteration
056         */
057        public void incCounter(long iteration) {
058            revise(iteration);
059            iCounter += 1.0;
060        }
061        
062        /** Set counter
063         * @param cnt new value
064         */
065        public void setCounter(double cnt) {
066            iCounter = cnt;
067        }
068        
069        /** Get counter
070         * @param iteration current iteration
071         */
072        public double getCounter(long iteration) {
073            if (iteration == 0l)
074                return iCounter;
075            if (iAgeing == 1.0)
076                return iCounter;
077            return iCounter * Math.pow(iAgeing, iteration - iLastRevision);
078        }
079        
080        /** Returns constraint */
081        public Constraint getConstraint() {
082            return iConstraint;
083        }
084        /** Sets constraint */
085        public void setConstraint(Constraint constraint) {
086            iConstraint = constraint;
087        }
088        
089        /** Revise counter. If ageing is used, counter is adopted to the current iteration: it is multiplited by ageing factor powered by the number of iterations since last revision.
090         */
091        public synchronized void revise(long iteration) {
092            if (iAgeing == 1.0)
093                return;
094            iCounter *= Math.pow(iAgeing, iteration - iLastRevision);
095            iLastRevision = iteration;
096        }
097        
098        /** Combine two integers (for hash code)
099         */
100        public static int combine(int a, int b) {
101            int ret = 0;
102            for (int i = 0; i < 15; i++)
103                ret = ret | ((a & (1 << i)) << i) | ((b & (1 << i)) << (i + 1));
104            return ret;
105        }
106        
107        public int hashCode() {
108            return iValue.hashCode();
109        }
110        
111        public boolean equals(Object o) {
112            if (o==null || !(o instanceof Assignment)) return false;
113            return ((Assignment)o).getValue().equals(getValue());
114        }
115        
116        /** Returns comparator of assignments */
117        public static java.util.Comparator getComparator(long iteration) {
118            return new AssignmentComparator(iteration);
119        }
120        
121        /** String representation */
122        public String toString() {
123            return toString(0l, true);
124        }
125        
126        /** String representation (e.g., 10x A := a)*/
127        public String toString(long iteration, boolean assignment) {
128            return (assignment ? getCounter(iteration) + "x " : "")
129                + getValue().variable().getName()
130                + (assignment ? " := " : " != ")
131                + getValue().getName();
132        }
133        
134        /** Compare two assignments (their counters) */
135        public int compareTo(long iteration, Assignment a) {
136            int cmp =
137            getValue().variable().getName().compareTo(
138            a.getValue().variable().getName());
139            if (cmp != 0)
140                return cmp;
141            if (getCounter(iteration) != a.getCounter(iteration))
142                return (getCounter(iteration) < a.getCounter(iteration) ? 1 : -1);
143                return getValue().getName().compareTo(a.getValue().getName());
144        }
145        
146        /** Assignment comparator */
147        public static class AssignmentComparator implements java.util.Comparator {
148            private long iIteration;
149            public AssignmentComparator(long iteration) {
150                iIteration = iteration;
151            }
152            public int compare(Object o1, Object o2) {
153                if (o1 == null
154                || o2 == null
155                || !(o1 instanceof Assignment)
156                || !(o2 instanceof Assignment))
157                    return 0;
158                return ((Assignment)o1).compareTo(iIteration, (Assignment)o2);
159            }
160        }
161    }