/* * Copyright (C) 2012-2013 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.samples; import java.io.StringReader; import de.uni_freiburg.informatik.ultimate.logic.Logics; import de.uni_freiburg.informatik.ultimate.logic.Script; import de.uni_freiburg.informatik.ultimate.logic.Script.LBool; import de.uni_freiburg.informatik.ultimate.logic.Term; import de.uni_freiburg.informatik.ultimate.smtinterpol.DefaultLogger; import de.uni_freiburg.informatik.ultimate.smtinterpol.option.OptionMap; import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.ParseEnvironment; import de.uni_freiburg.informatik.ultimate.smtinterpol.smtlib2.SMTInterpol; /** * This sample demonstrates the computation of tree interpolants for the famous * McCarthy 91 function using SMTInterpol. This sample is the API version of * the input script <tt>mccarthy.smt2</tt>. * @author Juergen Christ */ public final class TreeInterpolationSample { private TreeInterpolationSample() { // Hide constructor } public static void main(String[] unused) { // Create a logging proxy final DefaultLogger logger = new DefaultLogger(); // Create an option map to handle all API options. final OptionMap options = new OptionMap(logger, true); // Create a new solver final Script solver = new SMTInterpol(options); // Enable interpolant production solver.setOption(":produce-interpolants", Boolean.TRUE); // A parse environment to read from strings. This is a front end and // thus needs front end options. final ParseEnvironment pe = new ParseEnvironment(solver, options); // Disable success messages solver.setOption(":print-success", Boolean.FALSE); solver.setLogic(Logics.QF_LIA); // Declare some function symbols pe.parseStream(new StringReader("(declare-fun x_1 () Int)"), "x_1"); pe.parseStream(new StringReader("(declare-fun xm1 () Int)"), "xm1"); pe.parseStream(new StringReader("(declare-fun x2 () Int)"), "x2"); pe.parseStream(new StringReader("(declare-fun res4 () Int)"), "res4"); // Symbols above will be used in a second query. solver.push(1); pe.parseStream(new StringReader("(declare-fun resm5 () Int)"), "resm5"); pe.parseStream(new StringReader("(declare-fun xm6 () Int)"), "xm6"); pe.parseStream(new StringReader("(declare-fun x7 () Int)"), "x7"); pe.parseStream(new StringReader("(declare-fun res9 () Int)"), "res9"); pe.parseStream(new StringReader("(declare-fun resm10 () Int)"), "resm10"); pe.parseStream(new StringReader("(declare-fun res11 () Int)"), "res11"); // Assert all formulas. pe.parseStream(new StringReader( "(assert (! (<= x_1 100) :named M1))"), "M1"); pe.parseStream(new StringReader( "(assert (! (= xm1 (+ x_1 11)) :named M2))"), "M2"); pe.parseStream(new StringReader( "(assert (! (> x2 100) :named S11))"), "S11"); pe.parseStream(new StringReader( "(assert (! (= res4 (- x2 10)) :named S12))"), "S12"); pe.parseStream(new StringReader( "(assert (! (and (= x2 xm1) (= resm5 res4)) :named S1RET))"), "S1RET"); pe.parseStream(new StringReader( "(assert (! (= xm6 resm5) :named M3))"), "M3"); pe.parseStream(new StringReader( "(assert (! (> x7 100) :named S21))"), "S21"); pe.parseStream(new StringReader( "(assert (! (= res9 (- x7 10)) :named S22))"), "S22"); pe.parseStream(new StringReader( "(assert (! (and (= x7 xm6) (= resm10 res9)) :named S2RET))"), "S2RET"); pe.parseStream(new StringReader( "(assert (! (= res11 resm10) :named M4))"), "M4"); pe.parseStream(new StringReader( "(assert (! (and (<= x_1 101) (distinct res11 91)) :named ERR))" ), "ERR"); // Check for unsatisfiability LBool isSat = solver.checkSat(); if (isSat != LBool.UNSAT) { System.err.println("ERROR: Formula should be unsat!"); System.exit(1); } // Build up the formula tree Term[] partition = new Term[] { solver.term("M1"), solver.term("M2"), solver.term("S11"), solver.term("S12"), solver.term("S1RET"), solver.term("M3"), solver.term("S21"), solver.term("S22"), solver.term("S2RET"), solver.term("M4"), solver.term("ERR") }; // corresponding SMTLIB notation: // (get-interpolants M1 M2 (S11 S12) S1RET M3 (S21 S22) S2RET M4 ERR) // S11 and S12 are in the same subtree. The first element of this // subtree occurs at position 2 in the term array. // Similarly, S21 and S22 are in the same subtree which starts at // position 6. Term[] interpolants = solver.getInterpolants(partition, new int[] { 0, 0, 2, 2, 0, 0, 6, 6, 0, 0, 0 // NOCHECKSTYLE }); // Print the interpolants for (int i = 0; i < interpolants.length; ++i) { System.out.print(partition[i]); System.out.print(" is annotated with interpolant "); System.out.println(interpolants[i]); } // We omit the interpolant of the root. System.out.print(partition[interpolants.length]); System.out.println(" is annotated with interpolant false"); // Prepare second call solver.pop(1); solver.push(1); // We don't need to assert since all needed symbols survived. pe.parseStream(new StringReader( "(assert (! (<= x_1 100) :named M1))"), "M1"); pe.parseStream(new StringReader( "(assert (! (= xm1 (+ x_1 11)) :named M2))"), "M2"); pe.parseStream(new StringReader( "(assert (! (= x2 xm1) :named CALL))"), "CALL"); pe.parseStream(new StringReader( "(assert (! (> x2 100) :named S1))"), "S1"); pe.parseStream(new StringReader( "(assert (! (= res4 (- x2 10)) :named S2))"), "S2"); pe.parseStream(new StringReader( "(assert (! (and (<= x2 101) (distinct res4 91)) :named ERR))"), "ERR"); // Check for unsatisfiability isSat = solver.checkSat(); if (isSat != LBool.UNSAT) { System.err.println("ERROR: Formula should be unsat!"); System.exit(1); } // Second call: // (get-interpolants M1 M2 CALL S1 S2 ERR) // This is a non-tree version. We can simply use the non-tree API call. partition = new Term[] { solver.term("M1"), solver.term("M2"), solver.term("CALL"), solver.term("S1"), solver.term("S2"), solver.term("ERR") }; interpolants = solver.getInterpolants(partition); // Print the interpolants for (int i = 0; i < interpolants.length; ++i) { System.out.print(partition[i]); System.out.print(" is annotated with interpolant "); System.out.println(interpolants[i]); } // We omit the interpolant of the root. System.out.print(partition[interpolants.length]); System.out.println(" is annotated with interpolant false"); // Cleanup and exit solver.pop(1); solver.exit(); } }