001package net.sf.cpsolver.ifs.extension;
002
003import java.util.Comparator;
004
005import net.sf.cpsolver.ifs.model.Constraint;
006import 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 Tomáš Müller<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 */
034public 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}