001package org.cpsolver.ifs.assignment;
002
003import java.util.Collection;
004import java.util.HashMap;
005import java.util.HashSet;
006import java.util.LinkedHashMap;
007import java.util.Map;
008import java.util.Set;
009
010import org.cpsolver.ifs.assignment.context.InheritedAssignmentContextHolder;
011import org.cpsolver.ifs.model.Value;
012import org.cpsolver.ifs.model.Variable;
013import org.cpsolver.ifs.solution.Solution;
014
015
016/**
017 * Optimistic inherited assignment. This assignment does not expect the parent assignment to change
018 * much and it only remembers local changes made in this assignment. Use with caution. 
019 * 
020 * @see InheritedAssignment
021 * 
022 * @author  Tomáš Müller
023 * @version IFS 1.3 (Iterative Forward Search)<br>
024 *          Copyright (C) 2014 Tomáš Müller<br>
025 *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
026 *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
027 * <br>
028 *          This library is free software; you can redistribute it and/or modify
029 *          it under the terms of the GNU Lesser General Public License as
030 *          published by the Free Software Foundation; either version 3 of the
031 *          License, or (at your option) any later version. <br>
032 * <br>
033 *          This library is distributed in the hope that it will be useful, but
034 *          WITHOUT ANY WARRANTY; without even the implied warranty of
035 *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
036 *          Lesser General Public License for more details. <br>
037 * <br>
038 *          You should have received a copy of the GNU Lesser General Public
039 *          License along with this library; if not see <a href='http://www.gnu.org/licenses'>http://www.gnu.org/licenses</a>.
040 * @param <V> Variable
041 * @param <T> Value
042 **/
043public class OptimisticInheritedAssignment<V extends Variable<V, T>, T extends Value<V, T>> extends AssignmentAbstract<V, T> implements InheritedAssignment<V, T> {
044    private Assignment<V, T> iParent;
045    private Map<V, T> iAssignments = new LinkedHashMap<V, T>();
046    private Set<V> iDirty = new HashSet<V>();
047    private Map<V, Long> iIteration = new HashMap<V, Long>();
048    private long iVersion = -1;
049
050    public OptimisticInheritedAssignment(Solution<V, T> parent, int index) {
051        // super(new InheritedAssignmentContextHolder<V, T>(index, parent.getIteration()), index, parent);
052        super(new InheritedAssignmentContextHolder<V, T>(index, parent.getIteration()));
053        iParent = parent.getAssignment();
054        iVersion = parent.getIteration();
055    }
056    
057    @Override
058    public long getIteration(V variable) {
059        Long it = iIteration.get(variable);
060        return (it != null ? it : iDirty.contains(variable) ? 0 : iParent.getIteration(variable));
061    }
062
063    @Override
064    public Collection<V> assignedVariables() {
065        Set<V> variables = new HashSet<V>(iParent.assignedVariables());
066        variables.removeAll(iDirty);
067        variables.addAll(iAssignments.keySet());
068        return variables;
069    }
070    
071    @Override
072    public Collection<T> assignedValues() {
073        Set<T> values = new HashSet<T>();
074        for (T val: iParent.assignedValues()) {
075            if (val != null && !iDirty.contains(val.variable()))
076                values.add(val);
077        }
078        values.addAll(iAssignments.values());
079        return values;
080    }
081
082    @Override
083    public int nrAssignedVariables() {
084        return iAssignments.size() + iParent.nrAssignedVariables() - iDirty.size();
085    }
086    
087    @Override
088    protected T getValueInternal(V variable) {
089        T value = (iAssignments.isEmpty() ? null : iAssignments.get(variable));
090        return (value != null ? value : iDirty.contains(variable) ? null : iParent.getValue(variable));
091   }
092
093    @Override
094    protected void setValueInternal(long iteration, V variable, T value) {
095        if (value == null) {
096            iAssignments.remove(variable);
097            iIteration.remove(variable);
098            if (iParent.getValue(variable) != null)
099                iDirty.add(variable);
100        } else {
101            iAssignments.put(variable, value);
102            if (iteration > 0)
103                iIteration.put(variable, iteration);
104            iDirty.remove(variable);
105        }
106    }    
107    
108    @Override
109    public Assignment<V, T> getParentAssignment() {
110        return iParent;
111    }
112    
113    @Override
114    public long getVersion() {
115        return iVersion;
116    }
117}