/* * Copyright (C) 2016 Matthias Heizmann (heizmann@informatik.uni-freiburg.de) * Copyright (C) 2016 University of Freiburg * * This file is part of the ULTIMATE TraceAbstraction plug-in. * * The ULTIMATE TraceAbstraction plug-in 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. * * The ULTIMATE TraceAbstraction plug-in 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 the ULTIMATE TraceAbstraction plug-in. If not, see . * * Additional permission under GNU GPL version 3 section 7: * If you modify the ULTIMATE TraceAbstraction plug-in, or any covered work, by linking * or combining it with Eclipse RCP (or a modified version of Eclipse RCP), * containing parts covered by the terms of the Eclipse Public License, the * licensors of the ULTIMATE TraceAbstraction plug-in grant you additional permission * to convey the resulting work. */ package de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.hoaretriple; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.CfgSmtToolkit; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.structure.ICallAction; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.structure.IInternalAction; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.structure.IReturnAction; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.variables.IProgramNonOldVar; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.variables.IProgramVar; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.IPredicate; import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.IncrementalPlicationChecker.Validity; import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.SmtUtils; import de.uni_freiburg.informatik.ultimate.logic.Annotation; import de.uni_freiburg.informatik.ultimate.logic.ApplicationTerm; import de.uni_freiburg.informatik.ultimate.logic.Script.LBool; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.util.datastructures.relation.Pair; /** * Allows several preconditions. Tries to detect which of them are relevant to prove the implication. * * @author Matthias Heizmann (heizmann@informatik.uni-freiburg.de) */ public class HoareTripleCheckerWithPreconditionRelevanceAnalysis extends IncrementalHoareTripleChecker { private List mAssertedPrecond; public HoareTripleCheckerWithPreconditionRelevanceAnalysis(final CfgSmtToolkit csToolkit, final ILogger logger) { super(csToolkit, false); } private LBool assertPrecondition(final List pres) { assert mManagedScript.isLockOwner(this); assert mAssertedAction != null : "Assert CodeBlock first"; assert mAssertedPrecond == null : "precond already asserted"; mAssertedPrecond = pres; mEdgeCheckerBenchmark.continueEdgeCheckerTime(); mManagedScript.push(this, 1); LBool quickCheck = null; final Set vars = new HashSet<>(); for (int i = 0; i < pres.size(); i++) { Term predcondition = pres.get(i).getClosedFormula(); if (mUseNamedTerms) { final Annotation annot = new Annotation(":named", getIdentifierForPrecond(i)); predcondition = mManagedScript.annotate(this, predcondition, annot); } quickCheck = mManagedScript.assertTerm(this, predcondition); vars.addAll(pres.get(i).getVars()); } final String predProc = mAssertedAction.getPrecedingProcedure(); final Set modifiableGlobals = mModifiableGlobalVariableManager.getModifiedBoogieVars(predProc); final Collection oldVarEqualities = constructNonModOldVarsEquality(vars, modifiableGlobals, mManagedScript, this); if (!oldVarEqualities.isEmpty()) { Term nonModOldVarsEquality = SmtUtils.and(mManagedScript.getScript(), oldVarEqualities.toArray(new Term[oldVarEqualities.size()])); if (mUseNamedTerms) { final Annotation annot = new Annotation(":named", ID_PRECONDITION_NON_MOD_GLOBAL_EQUALITY); nonModOldVarsEquality = mManagedScript.annotate(this, nonModOldVarsEquality, annot); } quickCheck = mManagedScript.assertTerm(this, nonModOldVarsEquality); } mEdgeCheckerBenchmark.stopEdgeCheckerTime(); return quickCheck; } private String getIdentifierForPrecond(final int i) { return ID_PRECONDITION + i; } private void unAssertPrecondition() { assert mManagedScript.isLockOwner(this); assert mAssertedPrecond != null : "No PrePred asserted"; mAssertedPrecond = null; mManagedScript.pop(this, 1); if (mAssertedAction == null) { throw new AssertionError("CodeBlock is assigned first"); } } public Pair> checkInternal(final List pre, final IInternalAction act, final IPredicate post) { assertCodeBlock(act); assertPrecondition(pre); assertPostcond(post); final Validity validity = checkValidity(); final List preconditionsInUnsatCore; if (validity == Validity.VALID) { preconditionsInUnsatCore = determinePreconditionsInUnsatCore(); } else { preconditionsInUnsatCore = null; } unAssertPostcondition(); unAssertPrecondition(); unAssertCodeBlock(); return new Pair>(validity, preconditionsInUnsatCore); } private List determinePreconditionsInUnsatCore() { final Term[] unsatCore = mManagedScript.getUnsatCore(this); final Set idsInUnsatCore = new HashSet<>(); for (final Term term : unsatCore) { final ApplicationTerm appTerm = (ApplicationTerm) term; idsInUnsatCore.add(appTerm.getFunction().getApplicationString()); } final List result = new ArrayList<>(); for (int i = 0; i < mAssertedPrecond.size(); i++) { if (idsInUnsatCore.contains(getIdentifierForPrecond(i))) { result.add(mAssertedPrecond.get(i)); } } return result; } public Pair> checkCall(final List pre, final ICallAction act, final IPredicate post) { assertCodeBlock(act); assertPrecondition(pre); assertPostcond(post); final Validity validity = checkValidity(); final List preconditionsInUnsatCore; if (validity == Validity.VALID) { preconditionsInUnsatCore = determinePreconditionsInUnsatCore(); } else { preconditionsInUnsatCore = null; } unAssertPostcondition(); unAssertPrecondition(); unAssertCodeBlock(); return new Pair>(validity, preconditionsInUnsatCore); } public Pair> checkReturn(final List linPre, final IPredicate hierPre, final IReturnAction act, final IPredicate post) { assertCodeBlock(act); assertPrecondition(linPre); assertHierPred(hierPre); assertPostcond(post); final Validity validity = checkValidity(); final List preconditionsInUnsatCore; if (validity == Validity.VALID) { preconditionsInUnsatCore = determinePreconditionsInUnsatCore(); } else { preconditionsInUnsatCore = null; } unAssertPostcondition(); unAssertHierPred(); unAssertPrecondition(); unAssertCodeBlock(); return new Pair>(validity, preconditionsInUnsatCore); } }