/* * 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.convert; import java.util.Set; import java.util.Stack; import de.uni_freiburg.informatik.ultimate.logic.AnnotatedTerm; import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; import de.uni_freiburg.informatik.ultimate.logic.FormulaUnLet; import de.uni_freiburg.informatik.ultimate.logic.FormulaUnLet.UnletType; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.logic.TermVariable; import de.uni_freiburg.informatik.ultimate.logic.Theory; import de.uni_freiburg.informatik.ultimate.smtinterpol.util.CollectionsHelper; public class InferencePreparation { private final Theory mTeory; private final Set<TermVariable> mVars; private final Stack<Term> mBoolTerms; private Term mSubst; private ApplicationTerm mIte; public InferencePreparation(Theory theory,Set<TermVariable> vars) { mTeory = theory; mVars = vars; mBoolTerms = new Stack<Term>(); } public Term prepare(Term body) { assert body.getSort() == mTeory.getBooleanSort() : "Non-boolean term as quantifier sub?"; final FormulaUnLet unflet = new FormulaUnLet(UnletType.EXPAND_DEFINITIONS); return recprepare(unflet.unlet(body)); } private Term recprepare(Term subterm) { if (!CollectionsHelper.containsAny(subterm.getFreeVars(), mVars)) { return subterm; } while (subterm instanceof AnnotatedTerm) { subterm = ((AnnotatedTerm)subterm).getSubterm(); } if (subterm instanceof ApplicationTerm) { final ApplicationTerm app = (ApplicationTerm)subterm; if (app.getSort() == mTeory.getBooleanSort()) { mBoolTerms.push(subterm); } else if (app.getFunction().isIntern() && app.getFunction().getName().equals("ite")) { // Here, we have a term-ite... mSubst = mIte = app; return null; } final Term[] params = app.getParameters(); final Term[] newparams = new Term[params.length]; for (int i = 0; i < params.length; ++i) { newparams[i] = recprepare(params[i]); while (newparams[i] == null) { // Found term ite in parameter i // TODO This does not work: (and p q) vs. (p (f...)) if (mBoolTerms.peek() != subterm) { return null; } if (mBoolTerms.peek() == subterm) { mBoolTerms.pop(); return recprepare(generateIte(subterm)); } } } if (mBoolTerms.peek() == subterm) { mBoolTerms.pop(); } return mTeory.term(app.getFunction(), newparams); } return subterm; } private Term generateIte(Term subterm) { final Term trueCase = generateCase(subterm,true); final Term falseCase = generateCase(subterm,false); final Term res = mTeory.ifthenelse( mIte.getParameters()[0], trueCase, falseCase); mIte = null; mSubst = null; return res; } private Term generateCase(Term subterm,boolean which) { while (subterm instanceof AnnotatedTerm) { subterm = ((AnnotatedTerm)subterm).getSubterm(); } if (subterm == mSubst) { return mIte.getParameters()[which ? 1 : 2]; } if (subterm instanceof ApplicationTerm) { final ApplicationTerm at = (ApplicationTerm)subterm; final Term[] params = at.getParameters(); final Term[] newparams = new Term[params.length]; boolean changed = false; for (int i = 0; i < params.length; ++i) { newparams[i] = generateCase(params[i], which); changed |= params[i] != newparams[i]; } return changed ? mTeory.term(at.getFunction(),newparams) : at; } return subterm; } }