/*
* Copyright (C) 2020 Jonas Werner (wernerj@informatik.uni-freiburg.de)
* Copyright (C) 2020 University of Freiburg
*
* This file is part of the ULTIMATE accelerated interpolation library .
*
* The ULTIMATE framework 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 framework 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 accelerated interpolation library . If not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify the ULTIMATE PDR library , 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 accelerated interpolation library grant you additional permission
* to convey the resulting work.
*/
package de.uni_freiburg.informatik.ultimate.lib.acceleratedinterpolation;
import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;
import de.uni_freiburg.informatik.ultimate.automata.IRun;
import de.uni_freiburg.informatik.ultimate.automata.nestedword.NestedWord;
import de.uni_freiburg.informatik.ultimate.core.model.services.ILogger;
import de.uni_freiburg.informatik.ultimate.core.model.services.IUltimateServiceProvider;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.structure.IIcfgTransition;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.transitions.TransFormula;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.IPredicate;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.IPredicateUnifier;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.PredicateFactory;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.PredicateTransformer;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.predicates.PredicateUnifier;
import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.smt.tracecheck.ITraceCheckPreferences;
import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.ManagedScript;
import de.uni_freiburg.informatik.ultimate.lib.tracecheckerutils.Counterexample;
import de.uni_freiburg.informatik.ultimate.lib.tracecheckerutils.singletracecheck.InterpolatingTraceCheckCraig;
import de.uni_freiburg.informatik.ultimate.lib.tracecheckerutils.singletracecheck.InterpolationTechnique;
import de.uni_freiburg.informatik.ultimate.lib.tracecheckerutils.singletracecheck.TraceCheckUtils;
import de.uni_freiburg.informatik.ultimate.logic.Script.LBool;
import de.uni_freiburg.informatik.ultimate.logic.Term;
/**
* Interpolator used to generate interpolants from a given meta-trace
*
* @author Jonas Werner (wernerj@informatik.uni-freiburg.de)
*
* @param
* The transition.
*
*/
public class Interpolator> {
/**
* Define which technique of interpolation is used.
*
* @author Jonas Werner (wernerj@informatik.uni-freiburg.de)
*
*/
public enum InterpolationMethod {
POST, BINARY, CRAIG_NESTED, CRAIG_TREE
}
private final IPredicateUnifier mPredicateUnifier;
private final PredicateTransformer mPredTransformer;
private final ILogger mLogger;
private final ManagedScript mScript;
private final IUltimateServiceProvider mServices;
private final ITraceCheckPreferences mPrefs;
private IPredicate[] mInterpolants;
private LBool mTraceCheckResult;
/**
* The accelerated interpolation interpolator. Generates interpolants along a meta trace according to the specified
* interpolation method.
*
* @param predicateUnifier
* A {@link PredicateUnifier}
* @param predTransformer
* A {@link PredicateTransformer}
* @param logger
* A {@link ILogger}
* @param script
* A {@link ManagedScript}
* @param services
* An {@link IUltimateServiceProvider}
* @param prefs
* Ultimate's preferences as specified in the settings file.
*/
public Interpolator(final IPredicateUnifier predicateUnifier,
final PredicateTransformer predTransformer, final ILogger logger,
final ManagedScript script, final IUltimateServiceProvider services, final ITraceCheckPreferences prefs) {
mPredicateUnifier = predicateUnifier;
mPredTransformer = predTransformer;
mScript = script;
mLogger = logger;
mServices = services;
mPrefs = prefs;
}
/**
* Given a counterexample, like a meta-trace, generate a sequence of interpolants
*
* @param interpolationMethod
* which method of interpolation is used
* @param counterexample
* A possible counterexample trace.
*/
public void generateInterpolants(final InterpolationMethod interpolationMethod,
final IRun counterexample) {
switch (interpolationMethod) {
case POST:
mInterpolants = generateInterpolantsPost(counterexample);
return;
case CRAIG_NESTED:
mInterpolants = generateInterpolantsCraigNested(counterexample);
return;
default:
throw new UnsupportedOperationException();
}
}
/**
* Naive way of generating interpolants, by just applying the post operator
*
* @param counterexample
* @return
*/
private IPredicate[] generateInterpolantsPost(final IRun counterexampleRun) {
mTraceCheckResult = LBool.UNSAT;
final List counterexample = counterexampleRun.getWord().asList();
final IPredicate[] interpolants = new IPredicate[counterexample.size() + 1];
interpolants[0] = mPredicateUnifier.getTruePredicate();
interpolants[counterexample.size()] = mPredicateUnifier.getFalsePredicate();
for (int i = 1; i <= counterexample.size(); i++) {
interpolants[i] = mPredicateUnifier.getOrConstructPredicate(mPredTransformer
.strongestPostcondition(interpolants[i - 1], counterexample.get(i - 1).getTransformula()));
}
return Arrays.copyOfRange(interpolants, 1, counterexample.size());
}
/**
* Generation of interpolants by instantiating an {@link InterpolatingTraceCheckCraig} The code creates an
* InterpolatingTraceCheckCraig with settings for Craig_NestedInterpolation -- we could also try and wrap a strategy
* module to gain more flexibility.
*
* @param counterexample
* @return
*/
private IPredicate[] generateInterpolantsCraigNested(final IRun counterexampleRun) {
final List counterexample = counterexampleRun.getWord().asList();
final NestedWord nestedWord = TraceCheckUtils.toNestedWord(counterexample);
final TreeMap pendingContexts = new TreeMap<>();
final boolean instantiateArrayExt = true;
final boolean innerRecursiveNestedInterpolationCall = false;
final IPredicate preCondition = mPredicateUnifier.getTruePredicate();
final IPredicate postCondition = mPredicateUnifier.getFalsePredicate();
final var ctex = new Counterexample<>(nestedWord, counterexampleRun.getStateSequence());
final InterpolatingTraceCheckCraig itcc = new InterpolatingTraceCheckCraig<>(preCondition,
postCondition, pendingContexts, ctex, mServices, mPrefs.getCfgSmtToolkit(), mScript,
(PredicateFactory) mPredicateUnifier.getPredicateFactory(), mPredicateUnifier,
mPrefs.getAssertCodeBlockOrder(), mPrefs.computeCounterexample(), mPrefs.collectInterpolantStatistics(),
InterpolationTechnique.Craig_NestedInterpolation, instantiateArrayExt,
mPrefs.getSimplificationTechnique(), innerRecursiveNestedInterpolationCall);
mTraceCheckResult = itcc.isCorrect();
if (mTraceCheckResult == LBool.UNSAT) {
return itcc.getInterpolants();
}
return new IPredicate[0];
}
public LBool getTraceCheckResult() {
return mTraceCheckResult;
}
public IPredicate[] getInterpolants() {
return mInterpolants;
}
}