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