    001package net.sf.cpsolver.ifs.model;
    002
    003import java.util.HashSet;
    004import java.util.Set;
    005
    006import net.sf.cpsolver.ifs.util.IdGenerator;
    007
    008/**
    009 * Generic value. <br>
    010 * <br>
    011 * Every value has a notion about the variable it belongs to. It has also a
    012 * unique id. By default, every Value has an integer value which is used in
    013 * general heuristics, the task is than to minimimize the total value of
    014 * assigned values in the solution.
    015 *
    016 * @see Variable
    017 * @see Model
    018 * @see net.sf.cpsolver.ifs.solver.Solver
    019 *
    020 * @version IFS 1.2 (Iterative Forward Search)<br>
    021 *          Copyright (C) 2006 - 2010 Tomáš Müller<br>
    022 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
    023 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
    024 * <br>
    025 *          This library is free software; you can redistribute it and/or modify
    026 *          it under the terms of the GNU Lesser General Public License as
    027 *          published by the Free Software Foundation; either version 3 of the
    028 *          License, or (at your option) any later version. <br>
    029 * <br>
    030 *          This library is distributed in the hope that it will be useful, but
    031 *          WITHOUT ANY WARRANTY; without even the implied warranty of
    032 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    033 *          Lesser General Public License for more details. <br>
    034 * <br>
    035 *          You should have received a copy of the GNU Lesser General Public
    036 *          License along with this library; if not see
    037 *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
    038 */
    039public class Value<V extends Variable<V, T>, T extends Value<V, T>> implements Comparable<T> {
    040    private static IdGenerator sIdGenerator = new IdGenerator();
    041
    042    private long iId;
    043    private V iVariable = null;
    044
    045    private long iAssignmentCounter = 0;
    046    private long iLastAssignmentIteration = -1;
    047    private long iLastUnassignmentIteration = -1;
    048
    049    /** Integer value */
    050    protected double iValue = 0;
    051    /**
    052     * Extra information which can be used by an IFS extension (see
    053     * {@link net.sf.cpsolver.ifs.extension.Extension})
    054     */
    055    private Object iExtra = null;
    056
    057    /**
    058     * Constructor
    059     *
    060     * @param variable
    061     *            variable which the value belongs to
    062     */
    063    public Value(V variable) {
    064        iId = sIdGenerator.newId();
    065        iVariable = variable;
    066    }
    067
    068    /**
    069     * Constructor
    070     *
    071     * @param variable
    072     *            variable which the value belongs to
    073     * @param value
    074     *            integer value
    075     */
    076    public Value(V variable, double value) {
    077        iId = sIdGenerator.newId();
    078        iVariable = variable;
    079        iValue = value;
    080    }
    081
    082    /** Returns the variable which this value belongs to */
    083    public V variable() {
    084        return iVariable;
    085    }
    086
    087    /** Sets the variable which this value belongs to */
    088    @SuppressWarnings({ "unchecked", "rawtypes" })
    089    public void setVariable(Variable variable) {
    090        iVariable = (V) variable;
    091    }
    092
    093    /**
    094     * Notification (called by variable) that this value is assigned
    095     *
    096     * @param iteration
    097     *            current iteration
    098     */
    099    public void assigned(long iteration) {
    100        iAssignmentCounter++;
    101        iLastAssignmentIteration = iteration;
    102    }
    103
    104    /**
    105     * Notification (called by variable) that this value is unassigned
    106     *
    107     * @param iteration
    108     *            current iteration
    109     */
    110    public void unassigned(long iteration) {
    111        iLastUnassignmentIteration = iteration;
    112    }
    113
    114    /** Returns the iteration when the value was assigned at last (-1 if never). */
    115    public long lastAssignmentIteration() {
    116        return iLastAssignmentIteration;
    117    }
    118
    119    /**
    120     * Returns the iteration when the value was unassigned at last (-1 if
    121     * never).
    122     */
    123    public long lastUnassignmentIteration() {
    124        return iLastUnassignmentIteration;
    125    }
    126
    127    /** Returns the number of assignments of this value to its variable. */
    128    public long countAssignments() {
    129        return iAssignmentCounter;
    130    }
    131
    132    /** Unique id */
    133    public long getId() {
    134        return iId;
    135    }
    136
    137    /** Values name -- for printing purposes (E.g., Monday 7:30) */
    138    public String getName() {
    139        return String.valueOf(iId);
    140    }
    141
    142    /** Values description -- for printing purposes */
    143    public String getDescription() {
    144        return null;
    145    }
    146
    147    /**
    148     * Dobouble representaion. This allows us to have generic optimization
    149     * criteria. The task is than to minimize total value of assigned variables
    150     * of a solution.
    151     */
    152    public double toDouble() {
    153        return iValue;
    154    }
    155
    156    @Override
    157    public String toString() {
    158        return getName();
    159    }
    160
    161    @Override
    162    public int hashCode() {
    163        return (int) iId;
    164    }
    165
    166    /**
    167     * Comparison of two values which is based only on the value (not
    168     * appropriate variable etc.). toDouble() is compared by default.
    169     */
    170    public boolean valueEquals(T value) {
    171        if (value == null)
    172            return false;
    173        return toDouble() == value.toDouble();
    174    }
    175
    176    @Override
    177    public int compareTo(T value) {
    178        if (value == null)
    179            return -1;
    180        int cmp = Double.compare(toDouble(), value.toDouble());
    181        if (cmp != 0)
    182            return cmp;
    183        return Double.compare(getId(), value.getId());
    184    }
    185
    186    /** By default, comparison is made on unique ids */
    187    @Override
    188    public boolean equals(Object o) {
    189        if (o == null || !(o instanceof Value<?, ?>))
    190            return false;
    191        return getId() == ((Value<?, ?>) o).getId();
    192    }
    193
    194    /**
    195     * Extra information to which can be used by an extension (see
    196     * {@link net.sf.cpsolver.ifs.extension.Extension}).
    197     */
    198    public Object getExtra() {
    199        return iExtra;
    200    }
    201
    202    /**
    203     * Extra information to which can be used by an extension (see
    204     * {@link net.sf.cpsolver.ifs.extension.Extension}).
    205     */
    206    public void setExtra(Object object) {
    207        iExtra = object;
    208    }
    209
    210    /** True, if the value is consistent with the given value */
    211    @SuppressWarnings("unchecked")
    212    public boolean isConsistent(T value) {
    213        for (Constraint<V, T> constraint : iVariable.constraints()) {
    214            if (!constraint.isConsistent((T) this, value))
    215                return false;
    216        }
    217        for (Constraint<V, T> constraint : iVariable.getModel().globalConstraints()) {
    218            if (!constraint.isConsistent((T) this, value))
    219                return false;
    220        }
    221        return true;
    222    }
    223
    224    /**
    225     * Returns a set of conflicting values with this value. When empty, the
    226     * value is consistent with the existing assignment.
    227     */
    228    @SuppressWarnings("unchecked")
    229    public Set<T> conflicts() {
    230        HashSet<T> conflicts = new HashSet<T>();
    231        for (Constraint<V, T> constraint : iVariable.constraints()) {
    232            constraint.computeConflicts((T) this, conflicts);
    233        }
    234        for (Constraint<V, T> constraint : iVariable.getModel().globalConstraints()) {
    235            constraint.computeConflicts((T) this, conflicts);
    236        }
    237        if (!conflicts.isEmpty())
    238            return conflicts;
    239        return null;
    240    }
    241}