/* * 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.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; 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.cfg.transitions.TransFormulaBuilder; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.transitions.TransFormulaUtils; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.transitions.UnmodifiableTransFormula; import de.uni_freiburg.informatik.ultimate.lib.modelcheckerutils.cfg.transitions.UnmodifiableTransFormula.Infeasibility; 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.modelcheckerutils.smt.predicates.IPredicateUnifier; 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.smtlibutils.ManagedScript; import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.SmtUtils; import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.SmtUtils.SimplificationTechnique; import de.uni_freiburg.informatik.ultimate.lib.smtlibutils.Substitution; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.logic.TermVariable; /** * Class containing various functions helping with {@link IPredicate} transformation. * * @author Jonas Werner (wernerj@informatik.uni-freiburg.de) * * @param * Class of transition. */ public class PredicateHelper> { private final IPredicateUnifier mPredicateUnifier; private final PredicateTransformer mPredTransformer; private final ILogger mLogger; private final ManagedScript mScript; private final IUltimateServiceProvider mServices; /** * Construct a fresh {@link PredicateHelper} * * @param predicateUnifier * A {@link PredicateUnifier} * @param predTransformer * A {@link PredicateTransformer} * @param logger * A {@link ILogger} * @param script * A {@link ManagedScript} * @param services * {@link IUltimateServiceProvider} */ public PredicateHelper(final IPredicateUnifier predicateUnifier, final PredicateTransformer predTransformer, final ILogger logger, final ManagedScript script, final IUltimateServiceProvider services) { mPredicateUnifier = predicateUnifier; mPredTransformer = predTransformer; mScript = script; mLogger = logger; mServices = services; } /** * Convert a trace, given as a list of letters to a {@link UnmodifiableTransFormula} * * @param trace * The input trace to be converted. * @return The trace as {@link UnmodifiableTransFormula} */ public UnmodifiableTransFormula traceToTf(final List trace) { final List tfs = new ArrayList<>(); for (final LETTER l : trace) { tfs.add(l.getTransformula()); } return TransFormulaUtils.sequentialComposition(mLogger, mServices, mScript, false, false, false, SimplificationTechnique.SIMPLIFY_DDA, tfs); } /** * Convert a program trace into a list of singular transitions in form of {@link UnmodifiableTransFormula} * * @param trace * The trace to be converted. * @return A list of transitions. */ public List traceToListOfTfs(final List trace) { final List tfs = new ArrayList<>(); for (final LETTER l : trace) { tfs.add(l.getTransformula()); } return tfs; } /** * Replace variables in term with its default termvariables, needed for {@link IPredicate} creation * * @param t * {@link UnmodifiableTransFormula} to be transformed. * @return A {@link UnmodifiableTransFormula} where each Variable has been substituted by its default. */ public Term normalizeTerm(final UnmodifiableTransFormula t) { final HashMap subMap = new HashMap<>(); final Term tTerm = t.getFormula(); final Map inVars = new HashMap<>(); final Map outVars = new HashMap<>(); for (final Entry outVar : t.getOutVars().entrySet()) { subMap.put(outVar.getValue(), outVar.getKey().getTermVariable()); outVars.put(outVar.getKey(), outVar.getKey().getTermVariable()); } for (final Entry inVar : t.getInVars().entrySet()) { subMap.put(inVar.getValue(), inVar.getKey().getTermVariable()); inVars.put(inVar.getKey(), inVar.getKey().getTermVariable()); } return Substitution.apply(mScript, subMap, tTerm); } /** * Replace variables in term with its default termvariables, needed for {@link IPredicate} creation * * @param t * A transformulas term. * @param fresh * Are fresh variable instances needed. * @param tf * {@link UnmodifiableTransFormula} to be transformed. * @return A {@link UnmodifiableTransFormula} where each Variable has been substituted by its default. */ public UnmodifiableTransFormula normalizeTerm(final Term t, final UnmodifiableTransFormula tf, final Boolean fresh) { final HashMap subMap = new HashMap<>(); final Term tTerm = t; final Map inVars; final Map outVars; final Term newTerm; if (fresh) { inVars = new HashMap<>(); outVars = new HashMap<>(); for (final Entry outVar : tf.getOutVars().entrySet()) { final TermVariable newTV; newTV = mScript.constructFreshCopy(outVar.getKey().getTermVariable()); subMap.put(outVar.getValue(), newTV); outVars.put(outVar.getKey(), newTV); } for (final Entry inVar : tf.getInVars().entrySet()) { final TermVariable newTV; newTV = mScript.constructFreshCopy(inVar.getKey().getTermVariable()); subMap.put(inVar.getValue(), newTV); inVars.put(inVar.getKey(), newTV); } newTerm = Substitution.apply(mScript, subMap, tTerm); } else { inVars = new HashMap<>(tf.getInVars()); outVars = new HashMap<>(tf.getOutVars()); newTerm = tTerm; } final TransFormulaBuilder tfb = new TransFormulaBuilder(inVars, outVars, true, Collections.emptySet(), true, Collections.emptySet(), false); tfb.setFormula(newTerm); tfb.addAuxVarsButRenameToFreshCopies(tf.getAuxVars(), mScript); tfb.setInfeasibility(Infeasibility.NOT_DETERMINED); return tfb.finishConstruction(mScript); } /** * To make a given loopacceleration reflexive, create disjunction of acceleration and conjunction of equalities * between in and out vars * FIXME 20220925 Matthias: *
  • We do not have an ourvar for each invar *
  • Here we accidentally omit IProgramVars that occur only as outVar but not as invar * * @param t * A {@link Term} * @param acceleration * A {@link UnmodifiableTransFormula} representing a loopacceleration. * @return A reflexive loopacceleration. */ public Term makeReflexive(final Term t, final UnmodifiableTransFormula transitionFormula) { final Map invars = transitionFormula.getInVars(); final Map outvars = transitionFormula.getOutVars(); final List equalities = new ArrayList<>(); for (final Entry invar : invars.entrySet()) { final IProgramVar var = invar.getKey(); final TermVariable invarTV = invar.getValue(); final TermVariable outvarTV = outvars.get(var); final Term equality = mScript.getScript().term("=", invarTV, outvarTV); equalities.add(equality); } /* * TODO: empty conjunction = true! */ final Term conjunct = SmtUtils.and(mScript.getScript(), equalities); return SmtUtils.or(mScript.getScript(), t, conjunct); } /** * Check if an {@link IPredicate} contains vars from a {@link UnmodifiableTransFormula} * * @param predicate * The {@link IPredicate} * @param tf * The {@link UnmodifiableTransFormula} * @return true if the predicate contains vars, else false. */ public boolean predContainsTfVar(final IPredicate predicate, final UnmodifiableTransFormula tf) { final Set predVars = predicate.getVars(); final Set tfInVars = tf.getInVars().keySet(); final Set tfOutVars = tf.getOutVars().keySet(); for (final IProgramVar pv : predVars) { if (tfInVars.contains(pv) || tfOutVars.contains(pv)) { return true; } } return false; } }