    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}