001    package aima.logic.fol.inference.proof;
002    
003    import java.util.ArrayList;
004    import java.util.LinkedHashMap;
005    import java.util.List;
006    import java.util.Map;
007    
008    import aima.logic.fol.parsing.ast.Term;
009    import aima.logic.fol.parsing.ast.Variable;
010    
011    /**
012     * @author Ciaran O'Reilly
013     * 
014     */
015    public class ProofFinal implements Proof {
016            private Map<Variable, Term> answerBindings = new LinkedHashMap<Variable, Term>();
017            private ProofStep finalStep = null;
018            private List<ProofStep> proofSteps = null;
019    
020            public ProofFinal(ProofStep finalStep, Map<Variable, Term> answerBindings) {
021                    this.finalStep = finalStep;
022                    this.answerBindings.putAll(answerBindings);
023            }
024    
025            //
026            // START-Proof
027            public List<ProofStep> getSteps() {
028                    // Only calculate if the proof steps are actually requested.
029                    if (null == proofSteps) {
030                            calcualteProofSteps();
031                    }
032                    return proofSteps;
033            }
034    
035            public Map<Variable, Term> getAnswerBindings() {
036                    return answerBindings;
037            }
038    
039            public void replaceAnswerBindings(Map<Variable, Term> updatedBindings) {
040                    answerBindings.clear();
041                    answerBindings.putAll(updatedBindings);
042            }
043    
044            // END-Proof
045            //
046    
047            public String toString() {
048                    return answerBindings.toString();
049            }
050    
051            //
052            // PRIVATE METHODS
053            //
054            private void calcualteProofSteps() {
055                    proofSteps = new ArrayList<ProofStep>();
056                    addToProofSteps(finalStep);
057                    
058                    // Move all premises to the front of the
059                    // list of steps
060                    int to = 0;
061                    for (int i = 0; i < proofSteps.size(); i++) {
062                            if (proofSteps.get(i) instanceof ProofStepPremise) {
063                                    ProofStep m = proofSteps.remove(i);
064                                    proofSteps.add(to, m);
065                                    to++;
066                            }
067                    }
068                    
069                    // Move the Goals after the premises
070                    for (int i = 0; i < proofSteps.size(); i++) {
071                            if (proofSteps.get(i) instanceof ProofStepGoal) {
072                                    ProofStep m = proofSteps.remove(i);
073                                    proofSteps.add(to, m);
074                                    to++;
075                            }
076                    }
077    
078                    // Assign the step #s now that all the proof
079                    // steps have been unwound
080                    for (int i = 0; i < proofSteps.size(); i++) {
081                            proofSteps.get(i).setStepNumber(i + 1);
082                    }
083            }
084    
085            private void addToProofSteps(ProofStep step) {
086                    if (!proofSteps.contains(step)) {
087                            proofSteps.add(0, step);                        
088                    } else {
089                            proofSteps.remove(step);
090                            proofSteps.add(0, step);
091                    }
092                    List<ProofStep> predecessors = step.getPredecessorSteps();
093                    for (int i = predecessors.size() - 1; i >= 0; i--) {
094                            addToProofSteps(predecessors.get(i));
095                    }
096            }
097    }