001    package ifs.extension;
002    
003    import ifs.model.*;
004    import ifs.solver.*;
005    import ifs.util.*;
006    
007    import java.util.*;
008    
009    /**
010     * Computation of violated initial values (minimal perturbation problem).
011     * <br><br>
012     * It is using {@link Constraint#isConsistent(Value, Value)} to find out what 
013     * initial values (of different variables) cannot be assigned when an arbitrary value is
014     * assigned to a variable. This information is computed in advance, before the solver is
015     * executed. It is used for better estimation of perturbation penalty (see 
016     * {@link ifs.perturbations.PerturbationsCounter}) when a value is to be assigned to a variable.
017     *
018     * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
019     * @version 1.0
020     */
021    public class ViolatedInitials extends Extension {
022        private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(ViolatedInitials.class);
023        private Hashtable iViolatedInitials = new Hashtable();
024        
025        public ViolatedInitials(Solver solver, DataProperties properties) {
026            super(solver, properties);
027        }
028        
029        /** Compute the violations between any value and all other initial values */
030        public boolean init() {
031            sLogger.info("Computation of violated initials enabled.");
032            for (Enumeration i = getModel().variables().elements(); i.hasMoreElements();) {
033                Variable variable = (Variable)i.nextElement();
034                if (variable.getInitialAssignment() == null) continue;
035                for (Enumeration i1 = variable.constraints().elements(); i1.hasMoreElements();) {
036                    Constraint constraint = (Constraint)i1.nextElement();
037                    Vector conflicts = conflictValues(constraint, variable.getInitialAssignment());
038                    for (Enumeration i2 = conflicts.elements(); i2.hasMoreElements(); ) {
039                        Value value = (Value)i2.nextElement();
040                        addViolatedInitial(value, variable.getInitialAssignment());
041                    }
042                }
043            }
044            return true;
045        }
046        
047        /** Initial values that cannot be assigned when the given value is assigned */
048        public Set getViolatedInitials(Value value) {
049            return (Set)iViolatedInitials.get(value);
050        }
051        
052        private void addViolatedInitial(Value value, Value anotherValue) {
053            Set violations = (Set)iViolatedInitials.get(value);
054            if (violations == null) {
055                violations = new HashSet();
056                iViolatedInitials.put(value, violations);
057            }
058            violations.add(anotherValue);
059        }
060        
061        private Vector conflictValues(Constraint constraint, Value aValue) {
062            Vector ret = new FastVector();
063            for (Enumeration i1 = constraint.variables().elements();i1.hasMoreElements();) {
064                Variable variable = (Variable)i1.nextElement();
065                if (variable.equals(aValue.variable())) continue;
066                if (variable.getAssignment() != null) continue;
067                for (Enumeration i2 = variable.values().elements(); i2.hasMoreElements(); ) {
068                    Value value = (Value)i2.nextElement();
069                    if (!constraint.isConsistent(aValue, value))
070                        ret.addElement(value);
071                }
072            }
073            return ret;
074        }
075    }