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