001    /*
002     * Created on Sep 20, 2004
003     *
004     */
005    package aima.logic.fol;
006    
007    import java.util.ArrayList;
008    import java.util.List;
009    import java.util.Map;
010    
011    import aima.logic.fol.kb.data.Literal;
012    import aima.logic.fol.parsing.AbstractFOLVisitor;
013    import aima.logic.fol.parsing.ast.AtomicSentence;
014    import aima.logic.fol.parsing.ast.Function;
015    import aima.logic.fol.parsing.ast.QuantifiedSentence;
016    import aima.logic.fol.parsing.ast.Sentence;
017    import aima.logic.fol.parsing.ast.Term;
018    import aima.logic.fol.parsing.ast.Variable;
019    
020    /**
021     * @author Ravi Mohan
022     * @author Ciaran O'Reilly
023     */
024    public class SubstVisitor extends AbstractFOLVisitor {
025    
026            public SubstVisitor() {
027            }
028    
029            /**
030             * Note: Refer to Artificial Intelligence A Modern Approach (2nd Edition):
031             * page 273.
032             * 
033             * @param theta
034             *            a substitution.
035             * @param aSentence
036             *            the substitution has been applied to.
037             * @return a new Sentence representing the result of applying the
038             *         substitution theta to aSentence.
039             * 
040             */
041            public Sentence subst(Map<Variable, Term> theta, Sentence aSentence) {
042                    return (Sentence) aSentence.accept(this, theta);
043            }
044            
045            public Term subst(Map<Variable, Term> theta, Term aTerm) {
046                    return (Term) aTerm.accept(this, theta);
047            }
048            
049            public Function subst(Map<Variable, Term> theta, Function aFunction) {
050                    return (Function) aFunction.accept(this, theta);
051            }
052            
053            public Literal subst(Map<Variable, Term> theta, Literal aLiteral) {
054                    return aLiteral.newInstance(
055                                    (AtomicSentence) aLiteral.getAtomicSentence().accept(this,
056                                                    theta));
057            }
058    
059            @SuppressWarnings("unchecked")
060            @Override
061            public Object visitVariable(Variable variable, Object arg) {
062                    Map<Variable, Term> substitution = (Map<Variable, Term>) arg;
063                    if (substitution.containsKey(variable)) {
064                            return substitution.get(variable).copy();
065                    }
066                    return variable.copy();
067            }
068    
069            @SuppressWarnings("unchecked")
070            @Override
071            public Object visitQuantifiedSentence(QuantifiedSentence sentence,
072                            Object arg) {
073    
074                    Map<Variable, Term> substitution = (Map<Variable, Term>) arg;
075    
076                    Sentence quantified = sentence.getQuantified();
077                    Sentence quantifiedAfterSubs = (Sentence) quantified.accept(this, arg);
078    
079                    List<Variable> variables = new ArrayList<Variable>();
080                    for (Variable v : sentence.getVariables()) {
081                            Term st = substitution.get(v);
082                            if (null != st) {
083                                    if (st instanceof Variable) {
084                                            // Only if it is a variable to I replace it, otherwise
085                                            // I drop it.
086                                            variables.add((Variable) st.copy());
087                                    }
088                            } else {
089                                    // No substitution for the quantified variable, so
090                                    // keep it.
091                                    variables.add(v.copy());
092                            }
093                    }
094    
095                    // If not variables remaining on the quantifier, then drop it
096                    if (variables.size() == 0) {
097                            return quantifiedAfterSubs;
098                    }
099    
100                    return new QuantifiedSentence(sentence.getQuantifier(), variables,
101                                    quantifiedAfterSubs);
102            }
103    }