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 }