001    package net.sf.cpsolver.ifs.extension;
002    
003    
004    import java.util.*;
005    
006    import net.sf.cpsolver.ifs.model.*;
007    import net.sf.cpsolver.ifs.solver.*;
008    import net.sf.cpsolver.ifs.util.*;
009    
010    /**
011     * Computation of violated initial values (minimal perturbation problem).
012     * <br><br>
013     * It is using {@link Constraint#isConsistent(Value, Value)} to find out what 
014     * initial values (of different variables) cannot be assigned when an arbitrary value is
015     * assigned to a variable. This information is computed in advance, before the solver is
016     * executed. It is used for better estimation of perturbation penalty (see 
017     * {@link net.sf.cpsolver.ifs.perturbations.PerturbationsCounter}) when a value is to be assigned to a variable.
018     *
019     * @version
020     * IFS 1.1 (Iterative Forward Search)<br>
021     * Copyright (C) 2006 Tomáš Müller<br>
022     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
023     * Lazenska 391, 76314 Zlin, Czech Republic<br>
024     * <br>
025     * This library is free software; you can redistribute it and/or
026     * modify it under the terms of the GNU Lesser General Public
027     * License as published by the Free Software Foundation; either
028     * version 2.1 of the License, or (at your option) any later version.
029     * <br><br>
030     * This library is distributed in the hope that it will be useful,
031     * but 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.
034     * <br><br>
035     * You should have received a copy of the GNU Lesser General Public
036     * License along with this library; if not, write to the Free Software
037     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
038     */
039    public class ViolatedInitials extends Extension {
040        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ViolatedInitials.class);
041        private Hashtable iViolatedInitials = new Hashtable();
042        
043        public ViolatedInitials(Solver solver, DataProperties properties) {
044            super(solver, properties);
045        }
046        
047        /** Compute the violations between any value and all other initial values */
048        public boolean init() {
049            sLogger.info("Computation of violated initials enabled.");
050            for (Enumeration i = getModel().variables().elements(); i.hasMoreElements();) {
051                Variable variable = (Variable)i.nextElement();
052                if (variable.getInitialAssignment() == null) continue;
053                for (Enumeration i1 = variable.constraints().elements(); i1.hasMoreElements();) {
054                    Constraint constraint = (Constraint)i1.nextElement();
055                    Vector conflicts = conflictValues(constraint, variable.getInitialAssignment());
056                    for (Enumeration i2 = conflicts.elements(); i2.hasMoreElements(); ) {
057                        Value value = (Value)i2.nextElement();
058                        addViolatedInitial(value, variable.getInitialAssignment());
059                    }
060                }
061            }
062            return true;
063        }
064        
065        /** Initial values that cannot be assigned when the given value is assigned */
066        public Set getViolatedInitials(Value value) {
067            return (Set)iViolatedInitials.get(value);
068        }
069        
070        private void addViolatedInitial(Value value, Value anotherValue) {
071            Set violations = (Set)iViolatedInitials.get(value);
072            if (violations == null) {
073                violations = new HashSet();
074                iViolatedInitials.put(value, violations);
075            }
076            violations.add(anotherValue);
077        }
078        
079        private Vector conflictValues(Constraint constraint, Value aValue) {
080            Vector ret = new FastVector();
081            for (Enumeration i1 = constraint.variables().elements();i1.hasMoreElements();) {
082                Variable variable = (Variable)i1.nextElement();
083                if (variable.equals(aValue.variable())) continue;
084                if (variable.getAssignment() != null) continue;
085                for (Enumeration i2 = variable.values().elements(); i2.hasMoreElements(); ) {
086                    Value value = (Value)i2.nextElement();
087                    if (!constraint.isConsistent(aValue, value))
088                        ret.addElement(value);
089                }
090            }
091            return ret;
092        }
093    }