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