001    package aima.logic.fol;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.List;
006    import java.util.Map;
007    
008    import aima.logic.fol.kb.data.Chain;
009    import aima.logic.fol.kb.data.Clause;
010    import aima.logic.fol.kb.data.Literal;
011    import aima.logic.fol.parsing.FOLVisitor;
012    import aima.logic.fol.parsing.ast.ConnectedSentence;
013    import aima.logic.fol.parsing.ast.Constant;
014    import aima.logic.fol.parsing.ast.Function;
015    import aima.logic.fol.parsing.ast.NotSentence;
016    import aima.logic.fol.parsing.ast.Predicate;
017    import aima.logic.fol.parsing.ast.QuantifiedSentence;
018    import aima.logic.fol.parsing.ast.Sentence;
019    import aima.logic.fol.parsing.ast.Term;
020    import aima.logic.fol.parsing.ast.TermEquality;
021    import aima.logic.fol.parsing.ast.Variable;
022    
023    /**
024     * @author Ciaran O'Reilly
025     * 
026     */
027    public class StandardizeApartInPlace {
028            //
029            private static CollectAllVariables _collectAllVariables = new CollectAllVariables();
030    
031            public static int standardizeApart(Chain c, int saIdx) {
032                    List<Variable> variables = new ArrayList<Variable>();
033                    for (Literal l : c.getLiterals()) {
034                            collectAllVariables(l.getAtomicSentence(), variables);
035                    }
036                    
037                    return standardizeApart(variables, c, saIdx);
038            }
039            
040            public static int standardizeApart(Clause c, int saIdx) {
041                    List<Variable> variables = new ArrayList<Variable>();
042                    for (Literal l : c.getLiterals()) {
043                            collectAllVariables(l.getAtomicSentence(), variables);
044                    }
045                    
046                    return standardizeApart(variables, c, saIdx);
047            }
048            
049            //
050            // PRIVATE METHODS
051            //
052            private static int standardizeApart(List<Variable> variables, Object expr, int saIdx) {
053                    Map<String, Integer> indexicals = new HashMap<String, Integer>();
054                    for (Variable v : variables) {
055                            if (!indexicals.containsKey(v.getIndexedValue())) {
056                                    indexicals.put(v.getIndexedValue(), saIdx++);
057                            }
058                    }
059                    for (Variable v : variables) {
060                            Integer i = indexicals.get(v.getIndexedValue());
061                            if (null == i) {
062                                    throw new RuntimeException("ERROR: duplicate var=" + v + ", expr=" + expr);
063                            } else {
064                                    v.setIndexical(i);
065                            }
066                    }
067                    
068                    return saIdx;
069            }
070            
071            private static void collectAllVariables(Sentence s, List<Variable> vars) {
072                    s.accept(_collectAllVariables, vars);
073            }
074    }
075    
076    class CollectAllVariables implements FOLVisitor {
077            public CollectAllVariables() {
078                    
079            }
080            
081            @SuppressWarnings("unchecked")
082            public Object visitVariable(Variable var, Object arg) {
083                    List<Variable> variables = (List<Variable>) arg;
084                    variables.add(var);
085                    return var;
086            }
087    
088            @SuppressWarnings("unchecked")
089            public Object visitQuantifiedSentence(QuantifiedSentence sentence,
090                            Object arg) {
091                    // Ensure I collect quantified variables too
092                    List<Variable> variables = (List<Variable>) arg;
093                    variables.addAll(sentence.getVariables());
094    
095                    sentence.getQuantified().accept(this, arg);
096    
097                    return sentence;
098            }
099    
100            public Object visitPredicate(Predicate predicate, Object arg) {
101                    for (Term t : predicate.getTerms()) {
102                            t.accept(this, arg);
103                    }
104                    return predicate;
105            }
106    
107            public Object visitTermEquality(TermEquality equality, Object arg) {
108                    equality.getTerm1().accept(this, arg);
109                    equality.getTerm2().accept(this, arg);
110                    return equality;
111            }
112    
113            public Object visitConstant(Constant constant, Object arg) {
114                    return constant;
115            }
116    
117            public Object visitFunction(Function function, Object arg) {
118                    for (Term t : function.getTerms()) {
119                            t.accept(this, arg);
120                    }
121                    return function;
122            }
123    
124            public Object visitNotSentence(NotSentence sentence, Object arg) {
125                    sentence.getNegated().accept(this, arg);
126                    return sentence;
127            }
128    
129            public Object visitConnectedSentence(ConnectedSentence sentence, Object arg) {
130                    sentence.getFirst().accept(this, arg);
131                    sentence.getSecond().accept(this, arg);
132                    return sentence;
133            }
134    }