/* * Copyright (C) 2009-2012 University of Freiburg * * This file is part of SMTInterpol. * * SMTInterpol is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * SMTInterpol is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with SMTInterpol. If not, see <http://www.gnu.org/licenses/>. */ package de.uni_freiburg.informatik.ultimate.smtinterpol.proof; import java.util.ArrayDeque; import java.util.Deque; import java.util.HashMap; import java.util.Map; import de.uni_freiburg.informatik.ultimate.logic.Annotation; import de.uni_freiburg.informatik.ultimate.logic.NonRecursive; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.logic.Theory; import de.uni_freiburg.informatik.ultimate.smtinterpol.convert.SMTAffineTerm; import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.Clause; import de.uni_freiburg.informatik.ultimate.smtinterpol.dpll.IAnnotation; import de.uni_freiburg.informatik.ultimate.smtinterpol.proof.ResolutionNode.Antecedent; /** * A non-recursive proof tree printer. This class tries to avoid a stack * overflow by using an explicit stack that contains different visitors. * @author Juergen Christ */ public class ProofTermGenerator extends NonRecursive { private static class GenerateTerm implements Walker { private final Clause mCls; public GenerateTerm(Clause cls) { assert cls.getProof() instanceof ResolutionNode; mCls = cls; } @Override public void walk(NonRecursive nr) { final ProofTermGenerator engine = (ProofTermGenerator) nr; final Theory t = engine.getTheory(); final Antecedent[] antes = ((ResolutionNode) mCls.getProof()). getAntecedents(); final Term[] args = new Term[1 + antes.length]; args[0] = engine.getConverted(); for (int i = 0; i < antes.length; ++i) { args[i + 1] = t.annotatedTerm( new Annotation[] { new Annotation(":pivot", antes[i].mPivot.getSMTFormula(t, true))}, engine.getConverted()); } final Term res = t.term("@res", args); engine.setResult(mCls, res); engine.pushConverted(res); } } private static class Expander implements Walker { private final Clause mCls; public Expander(Clause cls) { mCls = cls; } @Override public void walk(NonRecursive nr) { final ProofTermGenerator engine = (ProofTermGenerator) nr; final Term known = engine.getTerm(mCls); if (known != null) { engine.pushConverted(known); return; } final ProofNode pn = mCls.getProof(); if (pn.isLeaf()) { final LeafNode ln = (LeafNode) pn; Term res; final Theory t = engine.getTheory(); final IAnnotation annot = ln.getTheoryAnnotation(); if (annot == null) { assert ln.getLeafKind() == LeafNode.ASSUMPTION; res = t.term("@assumption", mCls.toTerm(t)); } else { res = annot.toTerm(mCls, t); } engine.setResult(mCls, res); engine.pushConverted(res); } else { final ResolutionNode rn = (ResolutionNode) pn; engine.enqueueWalker(new GenerateTerm(mCls)); engine.enqueueWalker(new Expander(rn.getPrimary())); final Antecedent[] antes = rn.getAntecedents(); for (final Antecedent ante : antes) { engine.enqueueWalker(new Expander(ante.mAntecedent)); } } } } /** * Stack of recently produced antecedent names. */ private final Deque<Term> mConverted = new ArrayDeque<Term>(); /** * Theory used in sexpr conversion. */ private final Theory mTheory; /** * Mapping from clauses to terms representing the corresponding proof node. */ private final Map<Clause, Term> mNodes = new HashMap<Clause, Term>(); /** * Initialize the generator with a theory. * @param t The theory. */ public ProofTermGenerator(Theory t) { mTheory = t; } public Theory getTheory() { return mTheory; } Term getTerm(Clause cls) { return mNodes.get(cls); } Term getConverted() { return mConverted.pop(); } void pushConverted(Term res) { assert res.getSort().getName().equals("@Proof"); mConverted.push(res); } void setResult(Clause cls, Term res) { mNodes.put(cls, res); } public Term convert(Clause cls) { assert cls.getProof() != null; run(new Expander(cls)); final Term res = mConverted.pop(); return SMTAffineTerm.cleanup(res); } }