    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}