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