001    package aima.logic.fol;
002    
003    import java.util.ArrayList;
004    import java.util.HashMap;
005    import java.util.HashSet;
006    import java.util.List;
007    import java.util.Map;
008    import java.util.Set;
009    
010    import aima.logic.fol.inference.proof.ProofStepRenaming;
011    import aima.logic.fol.kb.data.Chain;
012    import aima.logic.fol.kb.data.Clause;
013    import aima.logic.fol.kb.data.Literal;
014    import aima.logic.fol.parsing.ast.AtomicSentence;
015    import aima.logic.fol.parsing.ast.Sentence;
016    import aima.logic.fol.parsing.ast.Term;
017    import aima.logic.fol.parsing.ast.Variable;
018    
019    /**
020     * @author Ciaran O'Reilly
021     * 
022     */
023    public class StandardizeApart {
024            private VariableCollector variableCollector = null;
025            private SubstVisitor substVisitor = null;
026    
027            public StandardizeApart() {
028                    variableCollector = new VariableCollector();
029                    substVisitor = new SubstVisitor();
030            }
031    
032            public StandardizeApart(VariableCollector variableCollector,
033                            SubstVisitor substVisitor) {
034                    this.variableCollector = variableCollector;
035                    this.substVisitor = substVisitor;
036            }
037    
038            // Note: see page 277.
039            public StandardizeApartResult standardizeApart(Sentence aSentence,
040                            StandardizeApartIndexical standardizeApartIndexical) {
041                    Set<Variable> toRename = variableCollector
042                                    .collectAllVariables(aSentence);
043                    Map<Variable, Term> renameSubstitution = new HashMap<Variable, Term>();
044                    Map<Variable, Term> reverseSubstitution = new HashMap<Variable, Term>();
045    
046                    for (Variable var : toRename) {
047                            Variable v = null;
048                            do {
049                                    v = new Variable(standardizeApartIndexical.getPrefix()
050                                                    + standardizeApartIndexical.getNextIndex());
051                                    // Ensure the new variable name is not already
052                                    // accidentally used in the sentence
053                            } while (toRename.contains(v));
054    
055                            renameSubstitution.put(var, v);
056                            reverseSubstitution.put(v, var);
057                    }
058    
059                    Sentence standardized = substVisitor.subst(renameSubstitution,
060                                    aSentence);
061    
062                    return new StandardizeApartResult(aSentence, standardized,
063                                    renameSubstitution, reverseSubstitution);
064            }
065    
066            public Clause standardizeApart(Clause clause,
067                            StandardizeApartIndexical standardizeApartIndexical) {
068    
069                    Set<Variable> toRename = variableCollector.collectAllVariables(clause);
070                    Map<Variable, Term> renameSubstitution = new HashMap<Variable, Term>();
071    
072                    for (Variable var : toRename) {
073                            Variable v = null;
074                            do {
075                                    v = new Variable(standardizeApartIndexical.getPrefix()
076                                                    + standardizeApartIndexical.getNextIndex());
077                                    // Ensure the new variable name is not already
078                                    // accidentally used in the sentence
079                            } while (toRename.contains(v));
080    
081                            renameSubstitution.put(var, v);
082                    }
083    
084                    if (renameSubstitution.size() > 0) {
085                            List<Literal> literals = new ArrayList<Literal>();
086    
087                            for (Literal l : clause.getLiterals()) {
088                                    literals.add(substVisitor.subst(renameSubstitution, l));
089                            }
090                            Clause renamed = new Clause(literals);
091                            renamed.setProofStep(new ProofStepRenaming(renamed,
092                                            clause.getProofStep()));
093                            return renamed;
094                    }
095    
096                    return clause;
097            }
098    
099            public Chain standardizeApart(Chain chain,
100                            StandardizeApartIndexical standardizeApartIndexical) {
101    
102                    Set<Variable> toRename = variableCollector.collectAllVariables(chain);
103                    Map<Variable, Term> renameSubstitution = new HashMap<Variable, Term>();
104    
105                    for (Variable var : toRename) {
106                            Variable v = null;
107                            do {
108                                    v = new Variable(standardizeApartIndexical.getPrefix()
109                                                    + standardizeApartIndexical.getNextIndex());
110                                    // Ensure the new variable name is not already
111                                    // accidentally used in the sentence
112                            } while (toRename.contains(v));
113    
114                            renameSubstitution.put(var, v);
115                    }
116    
117                    if (renameSubstitution.size() > 0) {
118                            List<Literal> lits = new ArrayList<Literal>();
119    
120                            for (Literal l : chain.getLiterals()) {
121                                    AtomicSentence atom = (AtomicSentence) substVisitor.subst(
122                                                    renameSubstitution, l.getAtomicSentence());
123                                    lits.add(l.newInstance(atom));
124                            }
125    
126                            Chain renamed = new Chain(lits);
127    
128                            renamed.setProofStep(new ProofStepRenaming(renamed,
129                                            chain.getProofStep()));
130    
131                            return renamed;
132                    }
133    
134                    return chain;
135            }
136    
137            public Map<Variable, Term> standardizeApart(List<Literal> l1Literals,
138                            List<Literal> l2Literals,
139                            StandardizeApartIndexical standardizeApartIndexical) {
140                    Set<Variable> toRename = new HashSet<Variable>();
141    
142                    for (Literal pl : l1Literals) {
143                            toRename.addAll(variableCollector.collectAllVariables(pl
144                                            .getAtomicSentence()));
145                    }
146                    for (Literal nl : l2Literals) {
147                            toRename.addAll(variableCollector.collectAllVariables(nl
148                                            .getAtomicSentence()));
149                    }
150    
151                    Map<Variable, Term> renameSubstitution = new HashMap<Variable, Term>();
152    
153                    for (Variable var : toRename) {
154                            Variable v = null;
155                            do {
156                                    v = new Variable(standardizeApartIndexical.getPrefix()
157                                                    + standardizeApartIndexical.getNextIndex());
158                                    // Ensure the new variable name is not already
159                                    // accidentally used in the sentence
160                            } while (toRename.contains(v));
161    
162                            renameSubstitution.put(var, v);
163                    }
164    
165                    List<Literal> posLits = new ArrayList<Literal>();
166                    List<Literal> negLits = new ArrayList<Literal>();
167    
168                    for (Literal pl : l1Literals) {
169                            posLits.add(substVisitor.subst(renameSubstitution, pl));
170                    }
171                    for (Literal nl : l2Literals) {
172                            negLits.add(substVisitor.subst(renameSubstitution, nl));
173                    }
174    
175                    l1Literals.clear();
176                    l1Literals.addAll(posLits);
177                    l2Literals.clear();
178                    l2Literals.addAll(negLits);
179    
180                    return renameSubstitution;
181            }
182    }