    001package org.cpsolver.ifs.model;
    002
    003import java.util.HashMap;
    004import java.util.Map;
    005import java.util.Set;
    006
    007import org.cpsolver.ifs.assignment.Assignment;
    008
    009
    010/**
    011 * A neighbour consisting of a change (either assignment or unassignment) of a
    012 * single variable.
    013 *
    014 * @see org.cpsolver.ifs.heuristics.NeighbourSelection
    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 *
    036 * @param <V> Variable
    037 * @param <T> Value
    038 */
    039public class SimpleNeighbour<V extends Variable<V, T>, T extends Value<V, T>> implements Neighbour<V, T> {
    040    private V iVariable = null;
    041    private T iValue = null;
    042    private Set<T> iConflicts = null;
    043
    044    /**
    045     * Model
    046     *
    047     * @param variable
    048     *            variable to be assigned
    049     * @param value
    050     *            value to be assigned to the given variable, null if the
    051     *            variable should be unassigned
    052     */
    053    public SimpleNeighbour(V variable, T value) {
    054        iVariable = variable;
    055        iValue = value;
    056    }
    057
    058    public SimpleNeighbour(V variable, T value, Set<T> conflicts) {
    059        iVariable = variable;
    060        iValue = value;
    061        iConflicts = conflicts;
    062    }
    063
    064    /** Selected variable
    065     * @return a variable
    066     **/
    067    public V getVariable() {
    068        return iVariable;
    069    }
    070
    071    /** Selected value
    072     * @return a value, null if the variable is to be unassigned
    073     **/
    074    public T getValue() {
    075        return iValue;
    076    }
    077
    078    /** Perform assignment */
    079    @Override
    080    public void assign(Assignment<V, T> assignment, long iteration) {
    081        if (iVariable == null)
    082            return;
    083        if (iConflicts != null)
    084            for (T conflict: iConflicts)
    085                assignment.unassign(iteration, conflict.variable());
    086        if (iValue != null)
    087            assignment.assign(iteration, iValue);
    088        else
    089            assignment.unassign(iteration, iVariable);
    090    }
    091
    092    /** Improvement in the solution value if this neighbour is accepted. */
    093    @Override
    094    public double value(Assignment<V, T> assignment) {
    095        T old = assignment.getValue(iVariable);
    096        // assigning an unassigned variable is always an improving move
    097        if (iValue != null && old == null && (iConflicts == null || iConflicts.isEmpty())) return -1;
    098        double val = (iValue == null ? 0 : iValue.toDouble(assignment)) - (iVariable == null || old == null ? 0 : old.toDouble(assignment));
    099        if (iConflicts != null)
    100            for (T conflict: iConflicts)
    101                val -= conflict.toDouble(assignment);
    102        return val;
    103    }
    104
    105    @Override
    106    public String toString() {
    107        return iVariable.getName() + " := " + (iValue == null ? "null" : iValue.getName());
    108    }
    109
    110    @Override
    111    public Map<V, T> assignments() {
    112        HashMap<V, T> ret = new HashMap<V, T>();
    113        if (iVariable != null)
    114            ret.put(iVariable, iValue);
    115        if (iConflicts != null)
    116            for (T conflict: iConflicts)
    117                ret.put(conflict.variable(), null);
    118        return ret;
    119    }
    120}