001package org.cpsolver.ifs.model;
002
003import java.util.HashMap;
004import java.util.Map;
005
006import org.cpsolver.ifs.assignment.Assignment;
007import org.cpsolver.ifs.model.Model;
008import org.cpsolver.ifs.model.Value;
009import org.cpsolver.ifs.model.Variable;
010
011
012/**
013 * Lazy swap of two variables. See {@link LazyNeighbour}.
014 *  
015 * @version IFS 1.3 (Iterative Forward Search)<br>
016 * Copyright (C) 2013 - 2014 Tomas Muller<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
021 * modify it under the terms of the GNU Lesser General Public
022 * License as published by the Free Software Foundation; either
023 * version 3 of the License, or (at your option) any later version.
024 * <br><br>
025 * This library is distributed in the hope that it will be useful,
026 * but 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.
029 * <br><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 * 
034 * @param <V> Variable 
035 * @param <T> Value
036 */
037public class LazySwap<V extends Variable<V, T>, T extends Value<V, T>> extends LazyNeighbour<V, T> {
038    private T iV1, iV2, iOldV1 = null, iOldV2 = null; 
039    
040    /**
041     * Constructor
042     * @param v1 first variable
043     * @param v2 second variable
044     */
045    public LazySwap(T v1, T v2) {
046        iV1 = v1;
047        iV2 = v2;
048    }
049    
050    /** Perform swap */
051    @Override
052    protected void doAssign(Assignment<V, T> assignment, long iteration) {
053        iOldV1 = assignment.getValue(iV1.variable());
054        iOldV2 = assignment.getValue(iV2.variable());
055        if (iOldV1 != null) assignment.unassign(iteration, iV1.variable());
056        if (iOldV2 != null) assignment.unassign(iteration, iV2.variable());
057        assignment.assign(iteration, iV1);
058        assignment.assign(iteration, iV2);
059    }
060    
061    /** Undo the swap */
062    @Override
063    protected void undoAssign(Assignment<V, T> assignment, long iteration) {
064        assignment.unassign(iteration, iV1.variable());
065        assignment.unassign(iteration, iV2.variable());
066        if (iOldV1 != null) assignment.assign(iteration, iOldV1);
067        if (iOldV2 != null) assignment.assign(iteration, iOldV2);
068    }
069    /** Return problem model */
070    @Override
071    public Model<V,T> getModel() {
072        return iV1.variable().getModel();
073    }
074    
075    /** String representation */
076    @Override
077    public String toString() {
078        return "Lazy "+iOldV1+" -> "+iV1+", "+iOldV2+" -> "+iV2;
079    }
080
081    @Override
082    public Map<V, T> assignments() {
083        Map<V, T> ret = new HashMap<V, T>();
084        ret.put(iV1.variable(), iV1);
085        ret.put(iV2.variable(), iV2);
086        return ret;
087    }
088
089}