001 package aima.logic.fol.inference; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 import java.util.Map; 006 import java.util.Set; 007 008 import aima.logic.fol.SubstVisitor; 009 import aima.logic.fol.Unifier; 010 import aima.logic.fol.VariableCollector; 011 import aima.logic.fol.parsing.FOLVisitor; 012 import aima.logic.fol.parsing.ast.AtomicSentence; 013 import aima.logic.fol.parsing.ast.ConnectedSentence; 014 import aima.logic.fol.parsing.ast.Constant; 015 import aima.logic.fol.parsing.ast.Function; 016 import aima.logic.fol.parsing.ast.NotSentence; 017 import aima.logic.fol.parsing.ast.Predicate; 018 import aima.logic.fol.parsing.ast.QuantifiedSentence; 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 * Abstract base class for Demodulation and Paramodulation algorithms. 025 */ 026 027 /** 028 * @author Ciaran O'Reilly 029 * 030 */ 031 public abstract class AbstractModulation { 032 // 033 // PROTECTED ATTRIBUTES 034 protected VariableCollector variableCollector = new VariableCollector(); 035 protected Unifier unifier = new Unifier(); 036 protected SubstVisitor substVisitor = new SubstVisitor(); 037 038 // 039 // PROTECTED METODS 040 // 041 protected abstract boolean isValidMatch(Term toMatch, 042 Set<Variable> toMatchVariables, Term possibleMatch, 043 Map<Variable, Term> substitution); 044 045 protected IdentifyCandidateMatchingTerm getMatchingSubstitution( 046 Term toMatch, AtomicSentence expression) { 047 048 IdentifyCandidateMatchingTerm icm = new IdentifyCandidateMatchingTerm( 049 toMatch, expression); 050 051 if (icm.isMatch()) { 052 return icm; 053 } 054 055 // indicates no match 056 return null; 057 } 058 059 protected class IdentifyCandidateMatchingTerm implements FOLVisitor { 060 private Term toMatch = null; 061 private Set<Variable> toMatchVariables = null; 062 private Term matchingTerm = null; 063 private Map<Variable, Term> substitution = null; 064 065 public IdentifyCandidateMatchingTerm(Term toMatch, 066 AtomicSentence expression) { 067 this.toMatch = toMatch; 068 this.toMatchVariables = variableCollector 069 .collectAllVariables(toMatch); 070 071 expression.accept(this, null); 072 } 073 074 public boolean isMatch() { 075 return null != matchingTerm; 076 } 077 078 public Term getMatchingTerm() { 079 return matchingTerm; 080 } 081 082 public Map<Variable, Term> getMatchingSubstitution() { 083 return substitution; 084 } 085 086 // 087 // START-FOLVisitor 088 public Object visitPredicate(Predicate p, Object arg) { 089 for (Term t : p.getArgs()) { 090 // Finish processing if have found a match 091 if (null != matchingTerm) { 092 break; 093 } 094 t.accept(this, null); 095 } 096 return p; 097 } 098 099 public Object visitTermEquality(TermEquality equality, Object arg) { 100 for (Term t : equality.getArgs()) { 101 // Finish processing if have found a match 102 if (null != matchingTerm) { 103 break; 104 } 105 t.accept(this, null); 106 } 107 return equality; 108 } 109 110 public Object visitVariable(Variable variable, Object arg) { 111 112 if (null != (substitution = unifier.unify(toMatch, variable))) { 113 if (isValidMatch(toMatch, toMatchVariables, variable, 114 substitution)) { 115 matchingTerm = variable; 116 } 117 } 118 119 return variable; 120 } 121 122 public Object visitConstant(Constant constant, Object arg) { 123 if (null != (substitution = unifier.unify(toMatch, constant))) { 124 if (isValidMatch(toMatch, toMatchVariables, constant, 125 substitution)) { 126 matchingTerm = constant; 127 } 128 } 129 130 return constant; 131 } 132 133 public Object visitFunction(Function function, Object arg) { 134 if (null != (substitution = unifier.unify(toMatch, function))) { 135 if (isValidMatch(toMatch, toMatchVariables, function, 136 substitution)) { 137 matchingTerm = function; 138 } 139 } 140 141 if (null == matchingTerm) { 142 // Try the Function's arguments 143 for (Term t : function.getArgs()) { 144 // Finish processing if have found a match 145 if (null != matchingTerm) { 146 break; 147 } 148 t.accept(this, null); 149 } 150 } 151 152 return function; 153 } 154 155 public Object visitNotSentence(NotSentence sentence, Object arg) { 156 throw new IllegalStateException( 157 "visitNotSentence() should not be called."); 158 } 159 160 public Object visitConnectedSentence(ConnectedSentence sentence, 161 Object arg) { 162 throw new IllegalStateException( 163 "visitConnectedSentence() should not be called."); 164 } 165 166 public Object visitQuantifiedSentence(QuantifiedSentence sentence, 167 Object arg) { 168 throw new IllegalStateException( 169 "visitQuantifiedSentence() should not be called."); 170 } 171 172 // END-FOLVisitor 173 // 174 } 175 176 protected class ReplaceMatchingTerm implements FOLVisitor { 177 private Term toReplace = null; 178 private Term replaceWith = null; 179 private boolean replaced = false; 180 181 public ReplaceMatchingTerm() { 182 } 183 184 public AtomicSentence replace(AtomicSentence expression, 185 Term toReplace, Term replaceWith) { 186 this.toReplace = toReplace; 187 this.replaceWith = replaceWith; 188 189 return (AtomicSentence) expression.accept(this, null); 190 } 191 192 // 193 // START-FOLVisitor 194 public Object visitPredicate(Predicate p, Object arg) { 195 List<Term> newTerms = new ArrayList<Term>(); 196 for (Term t : p.getTerms()) { 197 Term subsTerm = (Term) t.accept(this, arg); 198 newTerms.add(subsTerm); 199 } 200 return new Predicate(p.getPredicateName(), newTerms); 201 } 202 203 public Object visitTermEquality(TermEquality equality, Object arg) { 204 Term newTerm1 = (Term) equality.getTerm1().accept(this, arg); 205 Term newTerm2 = (Term) equality.getTerm2().accept(this, arg); 206 return new TermEquality(newTerm1, newTerm2); 207 } 208 209 public Object visitVariable(Variable variable, Object arg) { 210 if (!replaced) { 211 if (toReplace.equals(variable)) { 212 replaced = true; 213 return replaceWith; 214 } 215 } 216 return variable; 217 } 218 219 public Object visitConstant(Constant constant, Object arg) { 220 if (!replaced) { 221 if (toReplace.equals(constant)) { 222 replaced = true; 223 return replaceWith; 224 } 225 } 226 return constant; 227 } 228 229 public Object visitFunction(Function function, Object arg) { 230 if (!replaced) { 231 if (toReplace.equals(function)) { 232 replaced = true; 233 return replaceWith; 234 } 235 } 236 237 List<Term> newTerms = new ArrayList<Term>(); 238 for (Term t : function.getTerms()) { 239 Term subsTerm = (Term) t.accept(this, arg); 240 newTerms.add(subsTerm); 241 } 242 return new Function(function.getFunctionName(), newTerms); 243 } 244 245 public Object visitNotSentence(NotSentence sentence, Object arg) { 246 throw new IllegalStateException( 247 "visitNotSentence() should not be called."); 248 } 249 250 public Object visitConnectedSentence(ConnectedSentence sentence, 251 Object arg) { 252 throw new IllegalStateException( 253 "visitConnectedSentence() should not be called."); 254 } 255 256 public Object visitQuantifiedSentence(QuantifiedSentence sentence, 257 Object arg) { 258 throw new IllegalStateException( 259 "visitQuantifiedSentence() should not be called."); 260 } 261 262 // END-FOLVisitor 263 // 264 } 265 }