/*++ Copyright (c) 2012 Microsoft Corporation Module Name: Program.java Abstract: Z3 Java API: Example program Author: Christoph Wintersteiger (cwinter) 2012-11-27 Notes: --*/ package rba.tool.simulator.constraint.handlers; import java.util.*; import com.microsoft.z3.*; class JavaExample { @SuppressWarnings("serial") class TestFailedException extends Exception { public TestFailedException() { super("Check FAILED"); } }; // / Create axiom: function f is injective in the i-th argument. // / // / The following axiom is produced: // / // / forall (x_0, ..., x_n) finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i // / // / Where, finvis a fresh function declaration. public BoolExpr injAxiom(Context ctx, FuncDecl f, int i) { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); if (i >= sz) { System.out.println("failed to create inj axiom"); return null; } /* declare the i-th inverse of f: finv */ Sort finv_domain = f.getRange(); Sort finv_range = domain[i]; FuncDecl finv = ctx.mkFuncDecl("f_fresh", finv_domain, finv_range); /* allocate temporary arrays */ Expr[] xs = new Expr[sz]; Symbol[] names = new Symbol[sz]; Sort[] types = new Sort[sz]; /* fill types, names and xs */ for (int j = 0; j < sz; j++) { types[j] = domain[j]; names[j] = ctx.mkSymbol("x_" + Integer.toString(j)); xs[j] = ctx.mkBound(j, types[j]); } Expr x_i = xs[i]; /* create f(x_0, ..., x_i, ..., x_{n-1}) */ Expr fxs = f.apply(xs); /* create f_inv(f(x_0, ..., x_i, ..., x_{n-1})) */ Expr finv_fxs = finv.apply(fxs); /* create finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i */ Expr eq = ctx.mkEq(finv_fxs, x_i); /* use f(x_0, ..., x_i, ..., x_{n-1}) as the pattern for the quantifier */ Pattern p = ctx.mkPattern(fxs); /* create & assert quantifier */ BoolExpr q = ctx.mkForall(types, /* types of quantified variables */ names, /* names of quantified variables */ eq, 1, new Pattern[] { p } /* patterns */, null, null, null); return q; } // / Create axiom: function f is injective in the i-th argument. // / // / The following axiom is produced: // / // / forall (x_0, ..., x_n) finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i // / // / Where, finvis a fresh function declaration. public BoolExpr injAxiomAbs(Context ctx, FuncDecl f, int i) { Sort[] domain = f.getDomain(); int sz = f.getDomainSize(); if (i >= sz) { System.out.println("failed to create inj axiom"); return null; } /* declare the i-th inverse of f: finv */ Sort finv_domain = f.getRange(); Sort finv_range = domain[i]; FuncDecl finv = ctx.mkFuncDecl("f_fresh", finv_domain, finv_range); /* allocate temporary arrays */ Expr[] xs = new Expr[sz]; /* fill types, names and xs */ for (int j = 0; j < sz; j++) { xs[j] = ctx.mkConst("x_" + Integer.toString(j), domain[j]); } Expr x_i = xs[i]; /* create f(x_0, ..., x_i, ..., x_{n-1}) */ Expr fxs = f.apply(xs); /* create f_inv(f(x_0, ..., x_i, ..., x_{n-1})) */ Expr finv_fxs = finv.apply(fxs); /* create finv(f(x_0, ..., x_i, ..., x_{n-1})) = x_i */ Expr eq = ctx.mkEq(finv_fxs, x_i); /* use f(x_0, ..., x_i, ..., x_{n-1}) as the pattern for the quantifier */ Pattern p = ctx.mkPattern(fxs); /* create & assert quantifier */ BoolExpr q = ctx.mkForall(xs, /* types of quantified variables */ eq, /* names of quantified variables */ 1, new Pattern[] { p } /* patterns */, null, null, null); return q; } // / Assert the axiom: function f is commutative. // / // / This example uses the SMT-LIB parser to simplify the axiom // construction. // / private BoolExpr commAxiom(Context ctx, FuncDecl f) throws Exception { Sort t = f.getRange(); Sort[] dom = f.getDomain(); if (dom.length != 2 || !t.equals(dom[0]) || !t.equals(dom[1])) { System.out.println(Integer.toString(dom.length) + " " + dom[0].toString() + " " + dom[1].toString() + " " + t.toString()); throw new Exception( "function must be binary, and argument types must be equal to return type"); } String bench = "(benchmark comm :formula (forall (x " + t.getName() + ") (y " + t.getName() + ") (= (" + f.getName() + " x y) (" + f.getName() + " y x))))"; ctx.parseSMTLIBString(bench, new Symbol[] { t.getName() }, new Sort[] { t }, new Symbol[] { f.getName() }, new FuncDecl[] { f }); return ctx.getSMTLIBFormulas()[0]; } // / "Hello world" example: create a Z3 logical context, and delete it. public void simpleExample() { System.out.println("SimpleExample"); Log.append("SimpleExample"); { Context ctx = new Context(); /* do something with the context */ /* be kind to dispose manually and not wait for the GC. */ ctx.close(); } } Model check(Context ctx, BoolExpr f, Status sat) throws TestFailedException { Solver s = ctx.mkSolver(); s.add(f); if (s.check() != sat) throw new TestFailedException(); if (sat == Status.SATISFIABLE) return s.getModel(); else return null; } void solveTactical(Context ctx, Tactic t, Goal g, Status sat) throws TestFailedException { Solver s = ctx.mkSolver(t); System.out.println("\nTactical solver: " + s); for (BoolExpr a : g.getFormulas()) s.add(a); System.out.println("Solver: " + s); if (s.check() != sat) throw new TestFailedException(); } ApplyResult applyTactic(Context ctx, Tactic t, Goal g) { System.out.println("\nGoal: " + g); ApplyResult res = t.apply(g); System.out.println("Application result: " + res); Status q = Status.UNKNOWN; for (Goal sg : res.getSubgoals()) if (sg.isDecidedSat()) q = Status.SATISFIABLE; else if (sg.isDecidedUnsat()) q = Status.UNSATISFIABLE; switch (q) { case UNKNOWN: System.out.println("Tactic result: Undecided"); break; case SATISFIABLE: System.out.println("Tactic result: SAT"); break; case UNSATISFIABLE: System.out.println("Tactic result: UNSAT"); break; } return res; } void prove(Context ctx, BoolExpr f, boolean useMBQI) throws TestFailedException { BoolExpr[] assumptions = new BoolExpr[0]; prove(ctx, f, useMBQI, assumptions); } void prove(Context ctx, BoolExpr f, boolean useMBQI, BoolExpr... assumptions) throws TestFailedException { System.out.println("Proving: " + f); Solver s = ctx.mkSolver(); Params p = ctx.mkParams(); p.add("mbqi", useMBQI); s.setParameters(p); for (BoolExpr a : assumptions) s.add(a); s.add(ctx.mkNot(f)); Status q = s.check(); switch (q) { case UNKNOWN: System.out.println("Unknown because: " + s.getReasonUnknown()); break; case SATISFIABLE: throw new TestFailedException(); case UNSATISFIABLE: System.out.println("OK, proof: " + s.getProof()); break; } } void disprove(Context ctx, BoolExpr f, boolean useMBQI) throws TestFailedException { BoolExpr[] a = {}; disprove(ctx, f, useMBQI, a); } void disprove(Context ctx, BoolExpr f, boolean useMBQI, BoolExpr... assumptions) throws TestFailedException { System.out.println("Disproving: " + f); Solver s = ctx.mkSolver(); Params p = ctx.mkParams(); p.add("mbqi", useMBQI); s.setParameters(p); for (BoolExpr a : assumptions) s.add(a); s.add(ctx.mkNot(f)); Status q = s.check(); switch (q) { case UNKNOWN: System.out.println("Unknown because: " + s.getReasonUnknown()); break; case SATISFIABLE: System.out.println("OK, model: " + s.getModel()); break; case UNSATISFIABLE: throw new TestFailedException(); } } void modelConverterTest(Context ctx) throws TestFailedException { System.out.println("ModelConverterTest"); ArithExpr xr = (ArithExpr) ctx.mkConst(ctx.mkSymbol("x"), ctx.mkRealSort()); ArithExpr yr = (ArithExpr) ctx.mkConst(ctx.mkSymbol("y"), ctx.mkRealSort()); Goal g4 = ctx.mkGoal(true, false, false); g4.add(ctx.mkGt(xr, ctx.mkReal(10, 1))); g4.add(ctx.mkEq(yr, ctx.mkAdd(xr, ctx.mkReal(1, 1)))); g4.add(ctx.mkGt(yr, ctx.mkReal(1, 1))); ApplyResult ar = applyTactic(ctx, ctx.mkTactic("simplify"), g4); if (ar.getNumSubgoals() == 1 && (ar.getSubgoals()[0].isDecidedSat() || ar.getSubgoals()[0] .isDecidedUnsat())) throw new TestFailedException(); ar = applyTactic(ctx, ctx.andThen(ctx.mkTactic("simplify"), ctx.mkTactic("solve-eqs")), g4); if (ar.getNumSubgoals() == 1 && (ar.getSubgoals()[0].isDecidedSat() || ar.getSubgoals()[0] .isDecidedUnsat())) throw new TestFailedException(); Solver s = ctx.mkSolver(); for (BoolExpr e : ar.getSubgoals()[0].getFormulas()) s.add(e); Status q = s.check(); System.out.println("Solver says: " + q); System.out.println("Model: \n" + s.getModel()); System.out.println("Converted Model: \n" + ar.convertModel(0, s.getModel())); if (q != Status.SATISFIABLE) throw new TestFailedException(); } // / A simple array example. void arrayExample1(Context ctx) throws TestFailedException { System.out.println("ArrayExample1"); Log.append("ArrayExample1"); Goal g = ctx.mkGoal(true, false, false); ArraySort asort = ctx.mkArraySort(ctx.getIntSort(), ctx.mkBitVecSort(32)); ArrayExpr aex = (ArrayExpr) ctx.mkConst(ctx.mkSymbol("MyArray"), asort); Expr sel = ctx.mkSelect(aex, ctx.mkInt(0)); g.add(ctx.mkEq(sel, ctx.mkBV(42, 32))); Symbol xs = ctx.mkSymbol("x"); IntExpr xc = (IntExpr) ctx.mkConst(xs, ctx.getIntSort()); Symbol fname = ctx.mkSymbol("f"); Sort[] domain = { ctx.getIntSort() }; FuncDecl fd = ctx.mkFuncDecl(fname, domain, ctx.getIntSort()); Expr[] fargs = { ctx.mkConst(xs, ctx.getIntSort()) }; IntExpr fapp = (IntExpr) ctx.mkApp(fd, fargs); g.add(ctx.mkEq(ctx.mkAdd(xc, fapp), ctx.mkInt(123))); Solver s = ctx.mkSolver(); for (BoolExpr a : g.getFormulas()) s.add(a); System.out.println("Solver: " + s); Status q = s.check(); System.out.println("Status: " + q); if (q != Status.SATISFIABLE) throw new TestFailedException(); System.out.println("Model = " + s.getModel()); System.out.println("Interpretation of MyArray:\n" + s.getModel().getFuncInterp(aex.getFuncDecl())); System.out.println("Interpretation of x:\n" + s.getModel().getConstInterp(xc)); System.out.println("Interpretation of f:\n" + s.getModel().getFuncInterp(fd)); System.out.println("Interpretation of MyArray as Term:\n" + s.getModel().getFuncInterp(aex.getFuncDecl())); } // / Prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 // = i3 or select(a1, i3) = select(a2, i3)). // / This example demonstrates how to use the array // theory. public void arrayExample2(Context ctx) throws TestFailedException { System.out.println("ArrayExample2"); Log.append("ArrayExample2"); Sort int_type = ctx.getIntSort(); Sort array_type = ctx.mkArraySort(int_type, int_type); ArrayExpr a1 = (ArrayExpr) ctx.mkConst("a1", array_type); ArrayExpr a2 = ctx.mkArrayConst("a2", int_type, int_type); Expr i1 = ctx.mkConst("i1", int_type); Expr i2 = ctx.mkConst("i2", int_type); Expr i3 = ctx.mkConst("i3", int_type); Expr v1 = ctx.mkConst("v1", int_type); Expr v2 = ctx.mkConst("v2", int_type); Expr st1 = ctx.mkStore(a1, i1, v1); Expr st2 = ctx.mkStore(a2, i2, v2); Expr sel1 = ctx.mkSelect(a1, i3); Expr sel2 = ctx.mkSelect(a2, i3); /* create antecedent */ BoolExpr antecedent = ctx.mkEq(st1, st2); /* * create consequent: i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, * i3) */ BoolExpr consequent = ctx.mkOr(ctx.mkEq(i1, i3), ctx.mkEq(i2, i3), ctx.mkEq(sel1, sel2)); /* * prove store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = * i3 or select(a1, i3) = select(a2, i3)) */ BoolExpr thm = ctx.mkImplies(antecedent, consequent); System.out .println("prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3))"); System.out.println(thm); prove(ctx, thm, false); } // / Show that distinct(a_0, ... , a_n) is // / unsatisfiable when a_i's are arrays from boolean to // / boolean and n > 4. // / This example also shows how to use the distinct // construct. public void arrayExample3(Context ctx) throws TestFailedException { System.out.println("ArrayExample3"); Log.append("ArrayExample2"); for (int n = 2; n <= 5; n++) { System.out.println("n = " + Integer.toString(n)); Sort bool_type = ctx.mkBoolSort(); Sort array_type = ctx.mkArraySort(bool_type, bool_type); Expr[] a = new Expr[n]; /* create arrays */ for (int i = 0; i < n; i++) { a[i] = ctx.mkConst("array_" + Integer.toString(i), array_type); } /* assert distinct(a[0], ..., a[n]) */ BoolExpr d = ctx.mkDistinct(a); System.out.println(d); /* context is satisfiable if n < 5 */ Model model = check(ctx, d, n < 5 ? Status.SATISFIABLE : Status.UNSATISFIABLE); if (n < 5) { for (int i = 0; i < n; i++) { System.out.println(a[i].toString() + " = " + model.evaluate(a[i], false)); } } } } // / Sudoku solving example. void sudokuExample(Context ctx) throws TestFailedException { System.out.println("SudokuExample"); Log.append("SudokuExample"); // 9x9 matrix of integer variables IntExpr[][] X = new IntExpr[9][]; for (int i = 0; i < 9; i++) { X[i] = new IntExpr[9]; for (int j = 0; j < 9; j++) X[i][j] = (IntExpr) ctx.mkConst( ctx.mkSymbol("x_" + (i + 1) + "_" + (j + 1)), ctx.getIntSort()); } // each cell contains a value in {1, ..., 9} BoolExpr[][] cells_c = new BoolExpr[9][]; for (int i = 0; i < 9; i++) { cells_c[i] = new BoolExpr[9]; for (int j = 0; j < 9; j++) cells_c[i][j] = ctx.mkAnd(ctx.mkLe(ctx.mkInt(1), X[i][j]), ctx.mkLe(X[i][j], ctx.mkInt(9))); } // each row contains a digit at most once BoolExpr[] rows_c = new BoolExpr[9]; for (int i = 0; i < 9; i++) rows_c[i] = ctx.mkDistinct(X[i]); // each column contains a digit at most once BoolExpr[] cols_c = new BoolExpr[9]; for (int j = 0; j < 9; j++) cols_c[j] = ctx.mkDistinct(X[j]); // each 3x3 square contains a digit at most once BoolExpr[][] sq_c = new BoolExpr[3][]; for (int i0 = 0; i0 < 3; i0++) { sq_c[i0] = new BoolExpr[3]; for (int j0 = 0; j0 < 3; j0++) { IntExpr[] square = new IntExpr[9]; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) square[3 * i + j] = X[3 * i0 + i][3 * j0 + j]; sq_c[i0][j0] = ctx.mkDistinct(square); } } BoolExpr sudoku_c = ctx.mkTrue(); for (BoolExpr[] t : cells_c) sudoku_c = ctx.mkAnd(ctx.mkAnd(t), sudoku_c); sudoku_c = ctx.mkAnd(ctx.mkAnd(rows_c), sudoku_c); sudoku_c = ctx.mkAnd(ctx.mkAnd(cols_c), sudoku_c); for (BoolExpr[] t : sq_c) sudoku_c = ctx.mkAnd(ctx.mkAnd(t), sudoku_c); // sudoku instance, we use '0' for empty cells int[][] instance = { { 0, 0, 0, 0, 9, 4, 0, 3, 0 }, { 0, 0, 0, 5, 1, 0, 0, 0, 7 }, { 0, 8, 9, 0, 0, 0, 0, 4, 0 }, { 0, 0, 0, 0, 0, 0, 2, 0, 8 }, { 0, 6, 0, 2, 0, 1, 0, 5, 0 }, { 1, 0, 2, 0, 0, 0, 0, 0, 0 }, { 0, 7, 0, 0, 0, 0, 5, 2, 0 }, { 9, 0, 0, 0, 6, 5, 0, 0, 0 }, { 0, 4, 0, 9, 7, 0, 0, 0, 0 } }; BoolExpr instance_c = ctx.mkTrue(); for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) instance_c = ctx.mkAnd( instance_c, (BoolExpr) ctx.mkITE( ctx.mkEq(ctx.mkInt(instance[i][j]), ctx.mkInt(0)), ctx.mkTrue(), ctx.mkEq(X[i][j], ctx.mkInt(instance[i][j])))); Solver s = ctx.mkSolver(); s.add(sudoku_c); s.add(instance_c); if (s.check() == Status.SATISFIABLE) { Model m = s.getModel(); Expr[][] R = new Expr[9][9]; for (int i = 0; i < 9; i++) for (int j = 0; j < 9; j++) R[i][j] = m.evaluate(X[i][j], false); System.out.println("Sudoku solution:"); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) System.out.print(" " + R[i][j]); System.out.println(); } } else { System.out.println("Failed to solve sudoku"); throw new TestFailedException(); } } // / A basic example of how to use quantifiers. void quantifierExample1(Context ctx) { System.out.println("QuantifierExample"); Log.append("QuantifierExample"); Sort[] types = new Sort[3]; IntExpr[] xs = new IntExpr[3]; Symbol[] names = new Symbol[3]; IntExpr[] vars = new IntExpr[3]; for (int j = 0; j < 3; j++) { types[j] = ctx.getIntSort(); names[j] = ctx.mkSymbol("x_" + Integer.toString(j)); xs[j] = (IntExpr) ctx.mkConst(names[j], types[j]); vars[j] = (IntExpr) ctx.mkBound(2 - j, types[j]); // <-- vars // reversed! } Expr body_vars = ctx.mkAnd( ctx.mkEq(ctx.mkAdd(vars[0], ctx.mkInt(1)), ctx.mkInt(2)), ctx.mkEq(ctx.mkAdd(vars[1], ctx.mkInt(2)), ctx.mkAdd(vars[2], ctx.mkInt(3)))); Expr body_const = ctx.mkAnd( ctx.mkEq(ctx.mkAdd(xs[0], ctx.mkInt(1)), ctx.mkInt(2)), ctx.mkEq(ctx.mkAdd(xs[1], ctx.mkInt(2)), ctx.mkAdd(xs[2], ctx.mkInt(3)))); Expr x = ctx.mkForall(types, names, body_vars, 1, null, null, ctx.mkSymbol("Q1"), ctx.mkSymbol("skid1")); System.out.println("Quantifier X: " + x.toString()); Expr y = ctx.mkForall(xs, body_const, 1, null, null, ctx.mkSymbol("Q2"), ctx.mkSymbol("skid2")); System.out.println("Quantifier Y: " + y.toString()); } void quantifierExample2(Context ctx) { System.out.println("QuantifierExample2"); Log.append("QuantifierExample2"); Expr q1, q2; FuncDecl f = ctx.mkFuncDecl("f", ctx.getIntSort(), ctx.getIntSort()); FuncDecl g = ctx.mkFuncDecl("g", ctx.getIntSort(), ctx.getIntSort()); // Quantifier with Exprs as the bound variables. { Expr x = ctx.mkConst("x", ctx.getIntSort()); Expr y = ctx.mkConst("y", ctx.getIntSort()); Expr f_x = ctx.mkApp(f, x); Expr f_y = ctx.mkApp(f, y); Expr g_y = ctx.mkApp(g, y); @SuppressWarnings("unused") Pattern[] pats = new Pattern[] { ctx.mkPattern(f_x, g_y) }; Expr[] no_pats = new Expr[] { f_y }; Expr[] bound = new Expr[] { x, y }; Expr body = ctx.mkAnd(ctx.mkEq(f_x, f_y), ctx.mkEq(f_y, g_y)); q1 = ctx.mkForall(bound, body, 1, null, no_pats, ctx.mkSymbol("q"), ctx.mkSymbol("sk")); System.out.println(q1); } // Quantifier with de-Brujin indices. { Expr x = ctx.mkBound(1, ctx.getIntSort()); Expr y = ctx.mkBound(0, ctx.getIntSort()); Expr f_x = ctx.mkApp(f, x); Expr f_y = ctx.mkApp(f, y); Expr g_y = ctx.mkApp(g, y); @SuppressWarnings("unused") Pattern[] pats = new Pattern[] { ctx.mkPattern(f_x, g_y) }; Expr[] no_pats = new Expr[] { f_y }; Symbol[] names = new Symbol[] { ctx.mkSymbol("x"), ctx.mkSymbol("y") }; Sort[] sorts = new Sort[] { ctx.getIntSort(), ctx.getIntSort() }; Expr body = ctx.mkAnd(ctx.mkEq(f_x, f_y), ctx.mkEq(f_y, g_y)); q2 = ctx.mkForall(sorts, names, body, 1, null, // pats, no_pats, ctx.mkSymbol("q"), ctx.mkSymbol("sk")); System.out.println(q2); } System.out.println(q1.equals(q2)); } // / Prove that f(x, y) = f(w, v) implies y = v when // / f is injective in the second argument. public void quantifierExample3(Context ctx) throws TestFailedException { System.out.println("QuantifierExample3"); Log.append("QuantifierExample3"); /* * If quantified formulas are asserted in a logical context, then the * model produced by Z3 should be viewed as a potential model. */ /* declare function f */ Sort I = ctx.getIntSort(); FuncDecl f = ctx.mkFuncDecl("f", new Sort[] { I, I }, I); /* f is injective in the second argument. */ BoolExpr inj = injAxiom(ctx, f, 1); /* create x, y, v, w, fxy, fwv */ Expr x = ctx.mkIntConst("x"); Expr y = ctx.mkIntConst("y"); Expr v = ctx.mkIntConst("v"); Expr w = ctx.mkIntConst("w"); Expr fxy = ctx.mkApp(f, x, y); Expr fwv = ctx.mkApp(f, w, v); /* f(x, y) = f(w, v) */ BoolExpr p1 = ctx.mkEq(fxy, fwv); /* prove f(x, y) = f(w, v) implies y = v */ BoolExpr p2 = ctx.mkEq(y, v); prove(ctx, p2, false, inj, p1); /* disprove f(x, y) = f(w, v) implies x = w */ BoolExpr p3 = ctx.mkEq(x, w); disprove(ctx, p3, false, inj, p1); } // / Prove that f(x, y) = f(w, v) implies y = v when // / f is injective in the second argument. public void quantifierExample4(Context ctx) throws TestFailedException { System.out.println("QuantifierExample4"); Log.append("QuantifierExample4"); /* * If quantified formulas are asserted in a logical context, then the * model produced by Z3 should be viewed as a potential model. */ /* declare function f */ Sort I = ctx.getIntSort(); FuncDecl f = ctx.mkFuncDecl("f", new Sort[] { I, I }, I); /* f is injective in the second argument. */ BoolExpr inj = injAxiomAbs(ctx, f, 1); /* create x, y, v, w, fxy, fwv */ Expr x = ctx.mkIntConst("x"); Expr y = ctx.mkIntConst("y"); Expr v = ctx.mkIntConst("v"); Expr w = ctx.mkIntConst("w"); Expr fxy = ctx.mkApp(f, x, y); Expr fwv = ctx.mkApp(f, w, v); /* f(x, y) = f(w, v) */ BoolExpr p1 = ctx.mkEq(fxy, fwv); /* prove f(x, y) = f(w, v) implies y = v */ BoolExpr p2 = ctx.mkEq(y, v); prove(ctx, p2, false, inj, p1); /* disprove f(x, y) = f(w, v) implies x = w */ BoolExpr p3 = ctx.mkEq(x, w); disprove(ctx, p3, false, inj, p1); } // / Some basic tests. void basicTests(Context ctx) throws TestFailedException { System.out.println("BasicTests"); Symbol fname = ctx.mkSymbol("f"); Symbol x = ctx.mkSymbol("x"); Symbol y = ctx.mkSymbol("y"); Sort bs = ctx.mkBoolSort(); Sort[] domain = { bs, bs }; FuncDecl f = ctx.mkFuncDecl(fname, domain, bs); Expr fapp = ctx.mkApp(f, ctx.mkConst(x, bs), ctx.mkConst(y, bs)); Expr[] fargs2 = { ctx.mkFreshConst("cp", bs) }; Sort[] domain2 = { bs }; Expr fapp2 = ctx.mkApp(ctx.mkFreshFuncDecl("fp", domain2, bs), fargs2); BoolExpr trivial_eq = ctx.mkEq(fapp, fapp); BoolExpr nontrivial_eq = ctx.mkEq(fapp, fapp2); Goal g = ctx.mkGoal(true, false, false); g.add(trivial_eq); g.add(nontrivial_eq); System.out.println("Goal: " + g); Solver solver = ctx.mkSolver(); for (BoolExpr a : g.getFormulas()) solver.add(a); if (solver.check() != Status.SATISFIABLE) throw new TestFailedException(); ApplyResult ar = applyTactic(ctx, ctx.mkTactic("simplify"), g); if (ar.getNumSubgoals() == 1 && (ar.getSubgoals()[0].isDecidedSat() || ar.getSubgoals()[0] .isDecidedUnsat())) throw new TestFailedException(); ar = applyTactic(ctx, ctx.mkTactic("smt"), g); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedSat()) throw new TestFailedException(); g.add(ctx.mkEq(ctx.mkNumeral(1, ctx.mkBitVecSort(32)), ctx.mkNumeral(2, ctx.mkBitVecSort(32)))); ar = applyTactic(ctx, ctx.mkTactic("smt"), g); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat()) throw new TestFailedException(); Goal g2 = ctx.mkGoal(true, true, false); ar = applyTactic(ctx, ctx.mkTactic("smt"), g2); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedSat()) throw new TestFailedException(); g2 = ctx.mkGoal(true, true, false); g2.add(ctx.mkFalse()); ar = applyTactic(ctx, ctx.mkTactic("smt"), g2); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat()) throw new TestFailedException(); Goal g3 = ctx.mkGoal(true, true, false); Expr xc = ctx.mkConst(ctx.mkSymbol("x"), ctx.getIntSort()); Expr yc = ctx.mkConst(ctx.mkSymbol("y"), ctx.getIntSort()); g3.add(ctx.mkEq(xc, ctx.mkNumeral(1, ctx.getIntSort()))); g3.add(ctx.mkEq(yc, ctx.mkNumeral(2, ctx.getIntSort()))); BoolExpr constr = ctx.mkEq(xc, yc); g3.add(constr); ar = applyTactic(ctx, ctx.mkTactic("smt"), g3); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedUnsat()) throw new TestFailedException(); modelConverterTest(ctx); // Real num/den test. RatNum rn = ctx.mkReal(42, 43); Expr inum = rn.getNumerator(); Expr iden = rn.getDenominator(); System.out.println("Numerator: " + inum + " Denominator: " + iden); if (!inum.toString().equals("42") || !iden.toString().equals("43")) throw new TestFailedException(); if (!rn.toDecimalString(3).toString().equals("0.976?")) throw new TestFailedException(); bigIntCheck(ctx, ctx.mkReal("-1231231232/234234333")); bigIntCheck(ctx, ctx.mkReal("-123123234234234234231232/234234333")); bigIntCheck(ctx, ctx.mkReal("-234234333")); bigIntCheck(ctx, ctx.mkReal("234234333/2")); String bn = "1234567890987654321"; if (!ctx.mkInt(bn).getBigInteger().toString().equals(bn)) throw new TestFailedException(); if (!ctx.mkBV(bn, 128).getBigInteger().toString().equals(bn)) throw new TestFailedException(); if (ctx.mkBV(bn, 32).getBigInteger().toString().equals(bn)) throw new TestFailedException(); // Error handling test. try { @SuppressWarnings("unused") IntExpr i = ctx.mkInt("1/2"); throw new TestFailedException(); // unreachable } catch (Z3Exception e) { } } // / Some basic expression casting tests. void castingTest(Context ctx) throws TestFailedException { System.out.println("CastingTest"); Sort[] domain = { ctx.getBoolSort(), ctx.getBoolSort() }; FuncDecl f = ctx.mkFuncDecl("f", domain, ctx.getBoolSort()); AST upcast = ctx.mkFuncDecl(ctx.mkSymbol("q"), domain, ctx.getBoolSort()); try { @SuppressWarnings("unused") FuncDecl downcast = (FuncDecl) f; // OK } catch (ClassCastException e) { throw new TestFailedException(); } try { @SuppressWarnings("unused") Expr uc = (Expr) upcast; throw new TestFailedException(); // should not be reachable! } catch (ClassCastException e) { } Symbol s = ctx.mkSymbol(42); IntSymbol si = (s.getClass() == IntSymbol.class) ? (IntSymbol) s : null; if (si == null) throw new TestFailedException(); try { @SuppressWarnings("unused") IntSymbol si2 = (IntSymbol) s; } catch (ClassCastException e) { throw new TestFailedException(); } s = ctx.mkSymbol("abc"); StringSymbol ss = (s.getClass() == StringSymbol.class) ? (StringSymbol) s : null; if (ss == null) throw new TestFailedException(); try { @SuppressWarnings("unused") StringSymbol ss2 = (StringSymbol) s; } catch (ClassCastException e) { throw new TestFailedException(); } try { @SuppressWarnings("unused") IntSymbol si2 = (IntSymbol) s; throw new TestFailedException(); // unreachable } catch (Exception e) { } Sort srt = ctx.mkBitVecSort(32); BitVecSort bvs = null; try { bvs = (BitVecSort) srt; } catch (ClassCastException e) { throw new TestFailedException(); } if (bvs.getSize() != 32) throw new TestFailedException(); Expr q = ctx.mkAdd(ctx.mkInt(1), ctx.mkInt(2)); Expr q2 = q.getArgs()[1]; Sort qs = q2.getSort(); if (qs.getClass() != IntSort.class) throw new TestFailedException(); try { @SuppressWarnings("unused") IntSort isrt = (IntSort) qs; } catch (ClassCastException e) { throw new TestFailedException(); } AST a = ctx.mkInt(42); try { Expr.class.cast(a); } catch (ClassCastException e) { throw new TestFailedException(); } try { ArithExpr.class.cast(a); } catch (ClassCastException e) { throw new TestFailedException(); } try { IntExpr.class.cast(a); } catch (ClassCastException e) { throw new TestFailedException(); } try { IntNum.class.cast(a); } catch (ClassCastException e) { throw new TestFailedException(); } Expr[][] earr = new Expr[2][]; earr[0] = new Expr[2]; earr[1] = new Expr[2]; earr[0][0] = ctx.mkTrue(); earr[0][1] = ctx.mkTrue(); earr[1][0] = ctx.mkFalse(); earr[1][1] = ctx.mkFalse(); for (Expr[] ea : earr) for (Expr e : ea) { try { Expr ns = ctx.mkNot((BoolExpr) e); @SuppressWarnings("unused") BoolExpr ens = (BoolExpr) ns; } catch (ClassCastException ex) { throw new TestFailedException(); } } } // / Shows how to read an SMT1 file. void smt1FileTest(String filename) { System.out.print("SMT File test "); { HashMap cfg = new HashMap(); Context ctx = new Context(cfg); ctx.parseSMTLIBFile(filename, null, null, null, null); BoolExpr a = ctx.mkAnd(ctx.getSMTLIBFormulas()); System.out.println("read formula: " + a); } } // / Shows how to read an SMT2 file. void smt2FileTest(String filename) { Date before = new Date(); System.out.println("SMT2 File test "); System.gc(); { HashMap cfg = new HashMap(); cfg.put("model", "true"); Context ctx = new Context(cfg); Expr a = ctx.parseSMTLIB2File(filename, null, null, null, null); long t_diff = ((new Date()).getTime() - before.getTime()) / 1000; System.out.println("SMT2 file read time: " + t_diff + " sec"); // Iterate over the formula. LinkedList q = new LinkedList(); q.add(a); int cnt = 0; while (q.size() > 0) { AST cur = (AST) q.removeFirst(); cnt++; if (cur.getClass() == Expr.class) if (!(cur.isVar())) for (Expr c : ((Expr) cur).getArgs()) q.add(c); } System.out.println(cnt + " ASTs"); } long t_diff = ((new Date()).getTime() - before.getTime()) / 1000; System.out.println("SMT2 file test took " + t_diff + " sec"); } // / Shows how to use Solver(logic) // / @param ctx void logicExample(Context ctx) throws TestFailedException { System.out.println("LogicTest"); Log.append("LogicTest"); com.microsoft.z3.Global.ToggleWarningMessages(true); BitVecSort bvs = ctx.mkBitVecSort(32); Expr x = ctx.mkConst("x", bvs); Expr y = ctx.mkConst("y", bvs); BoolExpr eq = ctx.mkEq(x, y); // Use a solver for QF_BV Solver s = ctx.mkSolver("QF_BV"); s.add(eq); Status res = s.check(); System.out.println("solver result: " + res); // Or perhaps a tactic for QF_BV Goal g = ctx.mkGoal(true, false, false); g.add(eq); Tactic t = ctx.mkTactic("qfbv"); ApplyResult ar = t.apply(g); System.out.println("tactic result: " + ar); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedSat()) throw new TestFailedException(); } // / Demonstrates how to use the ParOr tactic. void parOrExample(Context ctx) throws TestFailedException { System.out.println("ParOrExample"); Log.append("ParOrExample"); BitVecSort bvs = ctx.mkBitVecSort(32); Expr x = ctx.mkConst("x", bvs); Expr y = ctx.mkConst("y", bvs); BoolExpr q = ctx.mkEq(x, y); Goal g = ctx.mkGoal(true, false, false); g.add(q); Tactic t1 = ctx.mkTactic("qfbv"); Tactic t2 = ctx.mkTactic("qfbv"); Tactic p = ctx.parOr(t1, t2); ApplyResult ar = p.apply(g); if (ar.getNumSubgoals() != 1 || !ar.getSubgoals()[0].isDecidedSat()) throw new TestFailedException(); } void bigIntCheck(Context ctx, RatNum r) { System.out.println("Num: " + r.getBigIntNumerator()); System.out.println("Den: " + r.getBigIntDenominator()); } // / Find a model for x xor y. public void findModelExample1(Context ctx) throws TestFailedException { System.out.println("FindModelExample1"); Log.append("FindModelExample1"); BoolExpr x = ctx.mkBoolConst("x"); BoolExpr y = ctx.mkBoolConst("y"); BoolExpr x_xor_y = ctx.mkXor(x, y); Model model = check(ctx, x_xor_y, Status.SATISFIABLE); System.out.println("x = " + model.evaluate(x, false) + ", y = " + model.evaluate(y, false)); } // / Find a model for x < y + 1, x > 2. // / Then, assert not(x = y), and find another model. public void findModelExample2(Context ctx) throws TestFailedException { System.out.println("FindModelExample2"); Log.append("FindModelExample2"); IntExpr x = ctx.mkIntConst("x"); IntExpr y = ctx.mkIntConst("y"); IntExpr one = ctx.mkInt(1); IntExpr two = ctx.mkInt(2); ArithExpr y_plus_one = ctx.mkAdd(y, one); BoolExpr c1 = ctx.mkLt(x, y_plus_one); BoolExpr c2 = ctx.mkGt(x, two); BoolExpr q = ctx.mkAnd(c1, c2); System.out.println("model for: x < y + 1, x > 2"); Model model = check(ctx, q, Status.SATISFIABLE); System.out.println("x = " + model.evaluate(x, false) + ", y =" + model.evaluate(y, false)); /* assert not(x = y) */ BoolExpr x_eq_y = ctx.mkEq(x, y); BoolExpr c3 = ctx.mkNot(x_eq_y); q = ctx.mkAnd(q, c3); System.out.println("model for: x < y + 1, x > 2, not(x = y)"); model = check(ctx, q, Status.SATISFIABLE); System.out.println("x = " + model.evaluate(x, false) + ", y = " + model.evaluate(y, false)); } // / Prove x = y implies g(x) = g(y), and // / disprove x = y implies g(g(x)) = g(y). // / This function demonstrates how to create uninterpreted // / types and functions. public void proveExample1(Context ctx) throws TestFailedException { System.out.println("ProveExample1"); Log.append("ProveExample1"); /* create uninterpreted type. */ Sort U = ctx.mkUninterpretedSort(ctx.mkSymbol("U")); /* declare function g */ FuncDecl g = ctx.mkFuncDecl("g", U, U); /* create x and y */ Expr x = ctx.mkConst("x", U); Expr y = ctx.mkConst("y", U); /* create g(x), g(y) */ Expr gx = g.apply(x); Expr gy = g.apply(y); /* assert x = y */ BoolExpr eq = ctx.mkEq(x, y); /* prove g(x) = g(y) */ BoolExpr f = ctx.mkEq(gx, gy); System.out.println("prove: x = y implies g(x) = g(y)"); prove(ctx, ctx.mkImplies(eq, f), false); /* create g(g(x)) */ Expr ggx = g.apply(gx); /* disprove g(g(x)) = g(y) */ f = ctx.mkEq(ggx, gy); System.out.println("disprove: x = y implies g(g(x)) = g(y)"); disprove(ctx, ctx.mkImplies(eq, f), false); /* Print the model using the custom model printer */ Model m = check(ctx, ctx.mkNot(f), Status.SATISFIABLE); System.out.println(m); } // / Prove not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0 // . // / Then, show that z < -1 is not implied. // / This example demonstrates how to combine uninterpreted // functions // / and arithmetic. public void proveExample2(Context ctx) throws TestFailedException { System.out.println("ProveExample2"); Log.append("ProveExample2"); /* declare function g */ Sort I = ctx.getIntSort(); FuncDecl g = ctx.mkFuncDecl("g", I, I); /* create x, y, and z */ IntExpr x = ctx.mkIntConst("x"); IntExpr y = ctx.mkIntConst("y"); IntExpr z = ctx.mkIntConst("z"); /* create gx, gy, gz */ Expr gx = ctx.mkApp(g, x); Expr gy = ctx.mkApp(g, y); Expr gz = ctx.mkApp(g, z); /* create zero */ IntExpr zero = ctx.mkInt(0); /* assert not(g(g(x) - g(y)) = g(z)) */ ArithExpr gx_gy = ctx.mkSub((IntExpr) gx, (IntExpr) gy); Expr ggx_gy = ctx.mkApp(g, gx_gy); BoolExpr eq = ctx.mkEq(ggx_gy, gz); BoolExpr c1 = ctx.mkNot(eq); /* assert x + z <= y */ ArithExpr x_plus_z = ctx.mkAdd(x, z); BoolExpr c2 = ctx.mkLe(x_plus_z, y); /* assert y <= x */ BoolExpr c3 = ctx.mkLe(y, x); /* prove z < 0 */ BoolExpr f = ctx.mkLt(z, zero); System.out .println("prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0"); prove(ctx, f, false, c1, c2, c3); /* disprove z < -1 */ IntExpr minus_one = ctx.mkInt(-1); f = ctx.mkLt(z, minus_one); System.out .println("disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1"); disprove(ctx, f, false, c1, c2, c3); } // / Show how push & pop can be used to create "backtracking" points. // / This example also demonstrates how big numbers can be // / created in ctx. public void pushPopExample1(Context ctx) throws TestFailedException { System.out.println("PushPopExample1"); Log.append("PushPopExample1"); /* create a big number */ IntSort int_type = ctx.getIntSort(); IntExpr big_number = ctx .mkInt("1000000000000000000000000000000000000000000000000000000"); /* create number 3 */ IntExpr three = (IntExpr) ctx.mkNumeral("3", int_type); /* create x */ IntExpr x = ctx.mkIntConst("x"); Solver solver = ctx.mkSolver(); /* assert x >= "big number" */ BoolExpr c1 = ctx.mkGe(x, big_number); System.out.println("assert: x >= 'big number'"); solver.add(c1); /* create a backtracking point */ System.out.println("push"); solver.push(); /* assert x <= 3 */ BoolExpr c2 = ctx.mkLe(x, three); System.out.println("assert: x <= 3"); solver.add(c2); /* context is inconsistent at this point */ if (solver.check() != Status.UNSATISFIABLE) throw new TestFailedException(); /* * backtrack: the constraint x <= 3 will be removed, since it was * asserted after the last ctx.Push. */ System.out.println("pop"); solver.pop(1); /* the context is consistent again. */ if (solver.check() != Status.SATISFIABLE) throw new TestFailedException(); /* new constraints can be asserted... */ /* create y */ IntExpr y = ctx.mkIntConst("y"); /* assert y > x */ BoolExpr c3 = ctx.mkGt(y, x); System.out.println("assert: y > x"); solver.add(c3); /* the context is still consistent. */ if (solver.check() != Status.SATISFIABLE) throw new TestFailedException(); } // / Tuples. // / Check that the projection of a tuple // / returns the corresponding element. public void tupleExample(Context ctx) throws TestFailedException { System.out.println("TupleExample"); Log.append("TupleExample"); Sort int_type = ctx.getIntSort(); TupleSort tuple = ctx.mkTupleSort(ctx.mkSymbol("mk_tuple"), // name of // tuple // constructor new Symbol[] { ctx.mkSymbol("first"), ctx.mkSymbol("second") }, // names // of // projection // operators new Sort[] { int_type, int_type } // types of projection // operators ); FuncDecl first = tuple.getFieldDecls()[0]; // declarations are for // projections @SuppressWarnings("unused") FuncDecl second = tuple.getFieldDecls()[1]; Expr x = ctx.mkConst("x", int_type); Expr y = ctx.mkConst("y", int_type); Expr n1 = tuple.mkDecl().apply(x, y); Expr n2 = first.apply(n1); BoolExpr n3 = ctx.mkEq(x, n2); System.out.println("Tuple example: " + n3); prove(ctx, n3, false); } // / Simple bit-vector example. // / // / This example disproves that x - 10 <= 0 IFF x <= 10 for (32-bit) // machine integers // / public void bitvectorExample1(Context ctx) throws TestFailedException { System.out.println("BitvectorExample1"); Log.append("BitvectorExample1"); Sort bv_type = ctx.mkBitVecSort(32); BitVecExpr x = (BitVecExpr) ctx.mkConst("x", bv_type); BitVecNum zero = (BitVecNum) ctx.mkNumeral("0", bv_type); BitVecNum ten = ctx.mkBV(10, 32); BitVecExpr x_minus_ten = ctx.mkBVSub(x, ten); /* bvsle is signed less than or equal to */ BoolExpr c1 = ctx.mkBVSLE(x, ten); BoolExpr c2 = ctx.mkBVSLE(x_minus_ten, zero); BoolExpr thm = ctx.mkIff(c1, c2); System.out .println("disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers"); disprove(ctx, thm, false); } // / Find x and y such that: x ^ y - 103 == x * y public void bitvectorExample2(Context ctx) throws TestFailedException { System.out.println("BitvectorExample2"); Log.append("BitvectorExample2"); /* construct x ^ y - 103 == x * y */ Sort bv_type = ctx.mkBitVecSort(32); BitVecExpr x = ctx.mkBVConst("x", 32); BitVecExpr y = ctx.mkBVConst("y", 32); BitVecExpr x_xor_y = ctx.mkBVXOR(x, y); BitVecExpr c103 = (BitVecNum) ctx.mkNumeral("103", bv_type); BitVecExpr lhs = ctx.mkBVSub(x_xor_y, c103); BitVecExpr rhs = ctx.mkBVMul(x, y); BoolExpr ctr = ctx.mkEq(lhs, rhs); System.out .println("find values of x and y, such that x ^ y - 103 == x * y"); /* find a model (i.e., values for x an y that satisfy the constraint */ Model m = check(ctx, ctr, Status.SATISFIABLE); System.out.println(m); } // / Demonstrates how to use the SMTLIB parser. public void parserExample1(Context ctx) throws TestFailedException { System.out.println("ParserExample1"); Log.append("ParserExample1"); ctx.parseSMTLIBString( "(benchmark tst :extrafuns ((x Int) (y Int)) :formula (> x y) :formula (> x 0))", null, null, null, null); for (BoolExpr f : ctx.getSMTLIBFormulas()) System.out.println("formula " + f); @SuppressWarnings("unused") Model m = check(ctx, ctx.mkAnd(ctx.getSMTLIBFormulas()), Status.SATISFIABLE); } // / Demonstrates how to initialize the parser symbol table. public void parserExample2(Context ctx) throws TestFailedException { System.out.println("ParserExample2"); Log.append("ParserExample2"); Symbol[] declNames = { ctx.mkSymbol("a"), ctx.mkSymbol("b") }; FuncDecl a = ctx.mkConstDecl(declNames[0], ctx.mkIntSort()); FuncDecl b = ctx.mkConstDecl(declNames[1], ctx.mkIntSort()); FuncDecl[] decls = new FuncDecl[] { a, b }; ctx.parseSMTLIBString("(benchmark tst :formula (> a b))", null, null, declNames, decls); BoolExpr f = ctx.getSMTLIBFormulas()[0]; System.out.println("formula: " + f); check(ctx, f, Status.SATISFIABLE); } // / Demonstrates how to initialize the parser symbol table. public void parserExample3(Context ctx) throws Exception { System.out.println("ParserExample3"); Log.append("ParserExample3"); /* declare function g */ Sort I = ctx.mkIntSort(); FuncDecl g = ctx.mkFuncDecl("g", new Sort[] { I, I }, I); BoolExpr ca = commAxiom(ctx, g); ctx.parseSMTLIBString( "(benchmark tst :formula (forall (x Int) (y Int) (implies (= x y) (= (gg x 0) (gg 0 y)))))", null, null, new Symbol[] { ctx.mkSymbol("gg") }, new FuncDecl[] { g }); BoolExpr thm = ctx.getSMTLIBFormulas()[0]; System.out.println("formula: " + thm); prove(ctx, thm, false, ca); } // / Display the declarations, assumptions and formulas in a SMT-LIB string. public void parserExample4(Context ctx) { System.out.println("ParserExample4"); Log.append("ParserExample4"); ctx.parseSMTLIBString( "(benchmark tst :extrafuns ((x Int) (y Int)) :assumption (= x 20) :formula (> x y) :formula (> x 0))", null, null, null, null); for (FuncDecl decl : ctx.getSMTLIBDecls()) { System.out.println("Declaration: " + decl); } for (BoolExpr f : ctx.getSMTLIBAssumptions()) { System.out.println("Assumption: " + f); } for (BoolExpr f : ctx.getSMTLIBFormulas()) { System.out.println("Formula: " + f); } } // / Demonstrates how to handle parser errors using Z3 error handling // support. // / public void parserExample5(Context ctx) { System.out.println("ParserExample5"); try { ctx.parseSMTLIBString( /* * the following string has a parsing error: missing * parenthesis */ "(benchmark tst :extrafuns ((x Int (y Int)) :formula (> x y) :formula (> x 0))", null, null, null, null); } catch (Z3Exception e) { System.out.println("Z3 error: " + e); } } // / Create an ite-Expr (if-then-else Exprs). public void iteExample(Context ctx) { System.out.println("ITEExample"); Log.append("ITEExample"); BoolExpr f = ctx.mkFalse(); Expr one = ctx.mkInt(1); Expr zero = ctx.mkInt(0); Expr ite = ctx.mkITE(f, one, zero); System.out.println("Expr: " + ite); } // / Create an enumeration data type. public void enumExample(Context ctx) throws TestFailedException { System.out.println("EnumExample"); Log.append("EnumExample"); Symbol name = ctx.mkSymbol("fruit"); EnumSort fruit = ctx.mkEnumSort(name, ctx.mkSymbol("apple"), ctx.mkSymbol("banana"), ctx.mkSymbol("orange")); System.out.println((fruit.getConsts()[0])); System.out.println((fruit.getConsts()[1])); System.out.println((fruit.getConsts()[2])); System.out.println((fruit.getTesterDecls()[0])); System.out.println((fruit.getTesterDecls()[1])); System.out.println((fruit.getTesterDecls()[2])); Expr apple = fruit.getConsts()[0]; Expr banana = fruit.getConsts()[1]; Expr orange = fruit.getConsts()[2]; /* Apples are different from oranges */ prove(ctx, ctx.mkNot(ctx.mkEq(apple, orange)), false); /* Apples pass the apple test */ prove(ctx, (BoolExpr) ctx.mkApp(fruit.getTesterDecls()[0], apple), false); /* Oranges fail the apple test */ disprove(ctx, (BoolExpr) ctx.mkApp(fruit.getTesterDecls()[0], orange), false); prove(ctx, (BoolExpr) ctx.mkNot((BoolExpr) ctx.mkApp( fruit.getTesterDecls()[0], orange)), false); Expr fruity = ctx.mkConst("fruity", fruit); /* If something is fruity, then it is an apple, banana, or orange */ prove(ctx, ctx.mkOr(ctx.mkEq(fruity, apple), ctx.mkEq(fruity, banana), ctx.mkEq(fruity, orange)), false); } // / Create a list datatype. public void listExample(Context ctx) throws TestFailedException { System.out.println("ListExample"); Log.append("ListExample"); Sort int_ty; ListSort int_list; Expr nil, l1, l2, x, y, u, v; BoolExpr fml, fml1; int_ty = ctx.mkIntSort(); int_list = ctx.mkListSort(ctx.mkSymbol("int_list"), int_ty); nil = ctx.mkConst(int_list.getNilDecl()); l1 = ctx.mkApp(int_list.getConsDecl(), ctx.mkInt(1), nil); l2 = ctx.mkApp(int_list.getConsDecl(), ctx.mkInt(2), nil); /* nil != cons(1, nil) */ prove(ctx, ctx.mkNot(ctx.mkEq(nil, l1)), false); /* cons(2,nil) != cons(1, nil) */ prove(ctx, ctx.mkNot(ctx.mkEq(l1, l2)), false); /* cons(x,nil) = cons(y, nil) => x = y */ x = ctx.mkConst("x", int_ty); y = ctx.mkConst("y", int_ty); l1 = ctx.mkApp(int_list.getConsDecl(), x, nil); l2 = ctx.mkApp(int_list.getConsDecl(), y, nil); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(x, y)), false); /* cons(x,u) = cons(x, v) => u = v */ u = ctx.mkConst("u", int_list); v = ctx.mkConst("v", int_list); l1 = ctx.mkApp(int_list.getConsDecl(), x, u); l2 = ctx.mkApp(int_list.getConsDecl(), y, v); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(u, v)), false); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(x, y)), false); /* is_nil(u) or is_cons(u) */ prove(ctx, ctx.mkOr((BoolExpr) ctx.mkApp(int_list.getIsNilDecl(), u), (BoolExpr) ctx.mkApp(int_list.getIsConsDecl(), u)), false); /* occurs check u != cons(x,u) */ prove(ctx, ctx.mkNot(ctx.mkEq(u, l1)), false); /* destructors: is_cons(u) => u = cons(head(u),tail(u)) */ fml1 = ctx.mkEq( u, ctx.mkApp(int_list.getConsDecl(), ctx.mkApp(int_list.getHeadDecl(), u), ctx.mkApp(int_list.getTailDecl(), u))); fml = ctx.mkImplies((BoolExpr) ctx.mkApp(int_list.getIsConsDecl(), u), fml1); System.out.println("Formula " + fml); prove(ctx, fml, false); disprove(ctx, fml1, false); } // / Create a binary tree datatype. public void treeExample(Context ctx) throws TestFailedException { System.out.println("TreeExample"); Log.append("TreeExample"); Sort cell; FuncDecl nil_decl, is_nil_decl, cons_decl, is_cons_decl, car_decl, cdr_decl; Expr nil, l1, l2, x, y, u, v; BoolExpr fml, fml1; String[] head_tail = new String[] { "car", "cdr" }; Sort[] sorts = new Sort[] { null, null }; int[] sort_refs = new int[] { 0, 0 }; Constructor nil_con, cons_con; nil_con = ctx.mkConstructor("nil", "is_nil", null, null, null); cons_con = ctx.mkConstructor("cons", "is_cons", head_tail, sorts, sort_refs); Constructor[] constructors = new Constructor[] { nil_con, cons_con }; cell = ctx.mkDatatypeSort("cell", constructors); nil_decl = nil_con.ConstructorDecl(); is_nil_decl = nil_con.getTesterDecl(); cons_decl = cons_con.ConstructorDecl(); is_cons_decl = cons_con.getTesterDecl(); FuncDecl[] cons_accessors = cons_con.getAccessorDecls(); car_decl = cons_accessors[0]; cdr_decl = cons_accessors[1]; nil = ctx.mkConst(nil_decl); l1 = ctx.mkApp(cons_decl, nil, nil); l2 = ctx.mkApp(cons_decl, l1, nil); /* nil != cons(nil, nil) */ prove(ctx, ctx.mkNot(ctx.mkEq(nil, l1)), false); /* cons(x,u) = cons(x, v) => u = v */ u = ctx.mkConst("u", cell); v = ctx.mkConst("v", cell); x = ctx.mkConst("x", cell); y = ctx.mkConst("y", cell); l1 = ctx.mkApp(cons_decl, x, u); l2 = ctx.mkApp(cons_decl, y, v); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(u, v)), false); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(x, y)), false); /* is_nil(u) or is_cons(u) */ prove(ctx, ctx.mkOr((BoolExpr) ctx.mkApp(is_nil_decl, u), (BoolExpr) ctx.mkApp(is_cons_decl, u)), false); /* occurs check u != cons(x,u) */ prove(ctx, ctx.mkNot(ctx.mkEq(u, l1)), false); /* destructors: is_cons(u) => u = cons(car(u),cdr(u)) */ fml1 = ctx.mkEq( u, ctx.mkApp(cons_decl, ctx.mkApp(car_decl, u), ctx.mkApp(cdr_decl, u))); fml = ctx.mkImplies((BoolExpr) ctx.mkApp(is_cons_decl, u), fml1); System.out.println("Formula " + fml); prove(ctx, fml, false); disprove(ctx, fml1, false); } // / Create a forest of trees. // / // / forest ::= nil | cons(tree, forest) // / tree ::= nil | cons(forest, forest) // / public void forestExample(Context ctx) throws TestFailedException { System.out.println("ForestExample"); Log.append("ForestExample"); Sort tree, forest; @SuppressWarnings("unused") FuncDecl nil1_decl, is_nil1_decl, cons1_decl, is_cons1_decl, car1_decl, cdr1_decl; @SuppressWarnings("unused") FuncDecl nil2_decl, is_nil2_decl, cons2_decl, is_cons2_decl, car2_decl, cdr2_decl; @SuppressWarnings("unused") Expr nil1, nil2, t1, t2, t3, t4, f1, f2, f3, l1, l2, x, y, u, v; // // Declare the names of the accessors for cons. // Then declare the sorts of the accessors. // For this example, all sorts refer to the new types 'forest' and // 'tree' // being declared, so we pass in null for both sorts1 and sorts2. // On the other hand, the sort_refs arrays contain the indices of the // two new sorts being declared. The first element in sort1_refs // points to 'tree', which has index 1, the second element in sort1_refs // array // points to 'forest', which has index 0. // Symbol[] head_tail1 = new Symbol[] { ctx.mkSymbol("head"), ctx.mkSymbol("tail") }; Sort[] sorts1 = new Sort[] { null, null }; int[] sort1_refs = new int[] { 1, 0 }; // the first item points to a // tree, the second to a forest Symbol[] head_tail2 = new Symbol[] { ctx.mkSymbol("car"), ctx.mkSymbol("cdr") }; Sort[] sorts2 = new Sort[] { null, null }; int[] sort2_refs = new int[] { 0, 0 }; // both items point to the forest // datatype. Constructor nil1_con, cons1_con, nil2_con, cons2_con; Constructor[] constructors1 = new Constructor[2], constructors2 = new Constructor[2]; Symbol[] sort_names = { ctx.mkSymbol("forest"), ctx.mkSymbol("tree") }; /* build a forest */ nil1_con = ctx.mkConstructor(ctx.mkSymbol("nil"), ctx.mkSymbol("is_nil"), null, null, null); cons1_con = ctx.mkConstructor(ctx.mkSymbol("cons1"), ctx.mkSymbol("is_cons1"), head_tail1, sorts1, sort1_refs); constructors1[0] = nil1_con; constructors1[1] = cons1_con; /* build a tree */ nil2_con = ctx.mkConstructor(ctx.mkSymbol("nil2"), ctx.mkSymbol("is_nil2"), null, null, null); cons2_con = ctx.mkConstructor(ctx.mkSymbol("cons2"), ctx.mkSymbol("is_cons2"), head_tail2, sorts2, sort2_refs); constructors2[0] = nil2_con; constructors2[1] = cons2_con; Constructor[][] clists = new Constructor[][] { constructors1, constructors2 }; Sort[] sorts = ctx.mkDatatypeSorts(sort_names, clists); forest = sorts[0]; tree = sorts[1]; // // Now that the datatype has been created. // Query the constructors for the constructor // functions, testers, and field accessors. // nil1_decl = nil1_con.ConstructorDecl(); is_nil1_decl = nil1_con.getTesterDecl(); cons1_decl = cons1_con.ConstructorDecl(); is_cons1_decl = cons1_con.getTesterDecl(); FuncDecl[] cons1_accessors = cons1_con.getAccessorDecls(); car1_decl = cons1_accessors[0]; cdr1_decl = cons1_accessors[1]; nil2_decl = nil2_con.ConstructorDecl(); is_nil2_decl = nil2_con.getTesterDecl(); cons2_decl = cons2_con.ConstructorDecl(); is_cons2_decl = cons2_con.getTesterDecl(); FuncDecl[] cons2_accessors = cons2_con.getAccessorDecls(); car2_decl = cons2_accessors[0]; cdr2_decl = cons2_accessors[1]; nil1 = ctx.mkConst(nil1_decl); nil2 = ctx.mkConst(nil2_decl); f1 = ctx.mkApp(cons1_decl, nil2, nil1); t1 = ctx.mkApp(cons2_decl, nil1, nil1); t2 = ctx.mkApp(cons2_decl, f1, nil1); t3 = ctx.mkApp(cons2_decl, f1, f1); t4 = ctx.mkApp(cons2_decl, nil1, f1); f2 = ctx.mkApp(cons1_decl, t1, nil1); f3 = ctx.mkApp(cons1_decl, t1, f1); /* nil != cons(nil,nil) */ prove(ctx, ctx.mkNot(ctx.mkEq(nil1, f1)), false); prove(ctx, ctx.mkNot(ctx.mkEq(nil2, t1)), false); /* cons(x,u) = cons(x, v) => u = v */ u = ctx.mkConst("u", forest); v = ctx.mkConst("v", forest); x = ctx.mkConst("x", tree); y = ctx.mkConst("y", tree); l1 = ctx.mkApp(cons1_decl, x, u); l2 = ctx.mkApp(cons1_decl, y, v); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(u, v)), false); prove(ctx, ctx.mkImplies(ctx.mkEq(l1, l2), ctx.mkEq(x, y)), false); /* is_nil(u) or is_cons(u) */ prove(ctx, ctx.mkOr((BoolExpr) ctx.mkApp(is_nil1_decl, u), (BoolExpr) ctx.mkApp(is_cons1_decl, u)), false); /* occurs check u != cons(x,u) */ prove(ctx, ctx.mkNot(ctx.mkEq(u, l1)), false); } // / Demonstrate how to use #Eval. public void evalExample1(Context ctx) { System.out.println("EvalExample1"); Log.append("EvalExample1"); IntExpr x = ctx.mkIntConst("x"); IntExpr y = ctx.mkIntConst("y"); IntExpr two = ctx.mkInt(2); Solver solver = ctx.mkSolver(); /* assert x < y */ solver.add(ctx.mkLt(x, y)); /* assert x > 2 */ solver.add(ctx.mkGt(x, two)); /* find model for the constraints above */ Model model = null; if (Status.SATISFIABLE == solver.check()) { model = solver.getModel(); System.out.println(model); System.out.println("\nevaluating x+y"); Expr v = model.evaluate(ctx.mkAdd(x, y), false); if (v != null) { System.out.println("result = " + (v)); } else { System.out.println("Failed to evaluate: x+y"); } } else { System.out.println("BUG, the constraints are satisfiable."); } } // / Demonstrate how to use #Eval on tuples. public void evalExample2(Context ctx) { System.out.println("EvalExample2"); Log.append("EvalExample2"); Sort int_type = ctx.getIntSort(); TupleSort tuple = ctx.mkTupleSort(ctx.mkSymbol("mk_tuple"), // name of // tuple // constructor new Symbol[] { ctx.mkSymbol("first"), ctx.mkSymbol("second") }, // names // of // projection // operators new Sort[] { int_type, int_type } // types of projection // operators ); FuncDecl first = tuple.getFieldDecls()[0]; // declarations are for // projections FuncDecl second = tuple.getFieldDecls()[1]; Expr tup1 = ctx.mkConst("t1", tuple); Expr tup2 = ctx.mkConst("t2", tuple); Solver solver = ctx.mkSolver(); /* assert tup1 != tup2 */ solver.add(ctx.mkNot(ctx.mkEq(tup1, tup2))); /* assert first tup1 = first tup2 */ solver.add(ctx.mkEq(ctx.mkApp(first, tup1), ctx.mkApp(first, tup2))); /* find model for the constraints above */ Model model = null; if (Status.SATISFIABLE == solver.check()) { model = solver.getModel(); System.out.println(model); System.out.println("evaluating tup1 " + (model.evaluate(tup1, false))); System.out.println("evaluating tup2 " + (model.evaluate(tup2, false))); System.out.println("evaluating second(tup2) " + (model.evaluate(ctx.mkApp(second, tup2), false))); } else { System.out.println("BUG, the constraints are satisfiable."); } } // / Demonstrate how to use Pushand Popto // / control the size of models. // / Note: this test is specialized to 32-bit bitvectors. public void checkSmall(Context ctx, Solver solver, BitVecExpr... to_minimize) { int num_Exprs = to_minimize.length; int[] upper = new int[num_Exprs]; int[] lower = new int[num_Exprs]; for (int i = 0; i < upper.length; ++i) { upper[i] = Integer.MAX_VALUE; lower[i] = 0; } boolean some_work = true; int last_index = -1; int last_upper = 0; while (some_work) { solver.push(); boolean check_is_sat = true; while (check_is_sat && some_work) { // Assert all feasible bounds. for (int i = 0; i < num_Exprs; ++i) { solver.add(ctx.mkBVULE(to_minimize[i], ctx.mkBV(upper[i], 32))); } check_is_sat = Status.SATISFIABLE == solver.check(); if (!check_is_sat) { if (last_index != -1) { lower[last_index] = last_upper + 1; } break; } System.out.println(solver.getModel()); // narrow the bounds based on the current model. for (int i = 0; i < num_Exprs; ++i) { Expr v = solver.getModel().evaluate(to_minimize[i], false); int ui = ((BitVecNum) v).getInt(); if (ui < upper[i]) { upper[i] = (int) ui; } System.out.println(i + " " + lower[i] + " " + upper[i]); } // find a new bound to add some_work = false; last_index = 0; for (int i = 0; i < num_Exprs; ++i) { if (lower[i] < upper[i]) { last_upper = (upper[i] + lower[i]) / 2; last_index = i; solver.add(ctx.mkBVULE(to_minimize[i], ctx.mkBV(last_upper, 32))); some_work = true; break; } } } solver.pop(); } } // / Reduced-size model generation example. public void findSmallModelExample(Context ctx) { System.out.println("FindSmallModelExample"); Log.append("FindSmallModelExample"); BitVecExpr x = ctx.mkBVConst("x", 32); BitVecExpr y = ctx.mkBVConst("y", 32); BitVecExpr z = ctx.mkBVConst("z", 32); Solver solver = ctx.mkSolver(); solver.add(ctx.mkBVULE(x, ctx.mkBVAdd(y, z))); checkSmall(ctx, solver, x, y, z); } // / Simplifier example. public void simplifierExample(Context ctx) { System.out.println("SimplifierExample"); Log.append("SimplifierExample"); IntExpr x = ctx.mkIntConst("x"); IntExpr y = ctx.mkIntConst("y"); IntExpr z = ctx.mkIntConst("z"); @SuppressWarnings("unused") IntExpr u = ctx.mkIntConst("u"); Expr t1 = ctx.mkAdd(x, ctx.mkSub(y, ctx.mkAdd(x, z))); Expr t2 = t1.simplify(); System.out.println((t1) + " -> " + (t2)); } // / Extract unsatisfiable core example public void unsatCoreAndProofExample(Context ctx) { System.out.println("UnsatCoreAndProofExample"); Log.append("UnsatCoreAndProofExample"); Solver solver = ctx.mkSolver(); BoolExpr pa = ctx.mkBoolConst("PredA"); BoolExpr pb = ctx.mkBoolConst("PredB"); BoolExpr pc = ctx.mkBoolConst("PredC"); BoolExpr pd = ctx.mkBoolConst("PredD"); BoolExpr p1 = ctx.mkBoolConst("P1"); BoolExpr p2 = ctx.mkBoolConst("P2"); BoolExpr p3 = ctx.mkBoolConst("P3"); BoolExpr p4 = ctx.mkBoolConst("P4"); BoolExpr[] assumptions = new BoolExpr[] { ctx.mkNot(p1), ctx.mkNot(p2), ctx.mkNot(p3), ctx.mkNot(p4) }; BoolExpr f1 = ctx.mkAnd(pa, pb, pc); BoolExpr f2 = ctx.mkAnd(pa, ctx.mkNot(pb), pc); BoolExpr f3 = ctx.mkOr(ctx.mkNot(pa), ctx.mkNot(pc)); BoolExpr f4 = pd; solver.add(ctx.mkOr(f1, p1)); solver.add(ctx.mkOr(f2, p2)); solver.add(ctx.mkOr(f3, p3)); solver.add(ctx.mkOr(f4, p4)); Status result = solver.check(assumptions); if (result == Status.UNSATISFIABLE) { System.out.println("unsat"); System.out.println("proof: " + solver.getProof()); System.out.println("core: "); for (Expr c : solver.getUnsatCore()) { System.out.println(c); } } } /// Extract unsatisfiable core example with AssertAndTrack public void unsatCoreAndProofExample2(Context ctx) { System.out.println("UnsatCoreAndProofExample2"); Log.append("UnsatCoreAndProofExample2"); Solver solver = ctx.mkSolver(); BoolExpr pa = ctx.mkBoolConst("PredA"); BoolExpr pb = ctx.mkBoolConst("PredB"); BoolExpr pc = ctx.mkBoolConst("PredC"); BoolExpr pd = ctx.mkBoolConst("PredD"); BoolExpr f1 = ctx.mkAnd(new BoolExpr[] { pa, pb, pc }); BoolExpr f2 = ctx.mkAnd(new BoolExpr[] { pa, ctx.mkNot(pb), pc }); BoolExpr f3 = ctx.mkOr(ctx.mkNot(pa), ctx.mkNot(pc)); BoolExpr f4 = pd; BoolExpr p1 = ctx.mkBoolConst("P1"); BoolExpr p2 = ctx.mkBoolConst("P2"); BoolExpr p3 = ctx.mkBoolConst("P3"); BoolExpr p4 = ctx.mkBoolConst("P4"); solver.assertAndTrack(f1, p1); solver.assertAndTrack(f2, p2); solver.assertAndTrack(f3, p3); solver.assertAndTrack(f4, p4); Status result = solver.check(); if (result == Status.UNSATISFIABLE) { System.out.println("unsat"); System.out.println("core: "); for (Expr c : solver.getUnsatCore()) { System.out.println(c); } } } public void finiteDomainExample(Context ctx) { System.out.println("FiniteDomainExample"); Log.append("FiniteDomainExample"); FiniteDomainSort s = ctx.mkFiniteDomainSort("S", 10); FiniteDomainSort t = ctx.mkFiniteDomainSort("T", 10); FiniteDomainNum s1 = (FiniteDomainNum)ctx.mkNumeral(1, s); FiniteDomainNum t1 = (FiniteDomainNum)ctx.mkNumeral(1, t); System.out.println(s); System.out.println(t); System.out.println(s1); System.out.println(t1); System.out.println(s1.getInt()); System.out.println(t1.getInt()); // But you cannot mix numerals of different sorts // even if the size of their domains are the same: // System.out.println(ctx.mkEq(s1, t1)); } public void floatingPointExample1(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample1"); Log.append("FloatingPointExample1"); FPSort s = ctx.mkFPSort(11, 53); System.out.println("Sort: " + s); FPNum x = (FPNum)ctx.mkNumeral("-1e1", s); /* -1 * 10^1 = -10 */ FPNum y = (FPNum)ctx.mkNumeral("-10", s); /* -10 */ FPNum z = (FPNum)ctx.mkNumeral("-1.25p3", s); /* -1.25 * 2^3 = -1.25 * 8 = -10 */ System.out.println("x=" + x.toString() + "; y=" + y.toString() + "; z=" + z.toString()); BoolExpr a = ctx.mkAnd(ctx.mkFPEq(x, y), ctx.mkFPEq(y, z)); check(ctx, ctx.mkNot(a), Status.UNSATISFIABLE); /* nothing is equal to NaN according to floating-point * equality, so NaN == k should be unsatisfiable. */ FPExpr k = (FPExpr)ctx.mkConst("x", s); FPExpr nan = ctx.mkFPNaN(s); /* solver that runs the default tactic for QF_FP. */ Solver slvr = ctx.mkSolver("QF_FP"); slvr.add(ctx.mkFPEq(nan, k)); if (slvr.check() != Status.UNSATISFIABLE) throw new TestFailedException(); System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); /* NaN is equal to NaN according to normal equality. */ slvr = ctx.mkSolver("QF_FP"); slvr.add(ctx.mkEq(nan, nan)); if (slvr.check() != Status.SATISFIABLE) throw new TestFailedException(); System.out.println("OK, sat:" + System.getProperty("line.separator") + slvr); /* Let's prove -1e1 * -1.25e3 == +100 */ x = (FPNum)ctx.mkNumeral("-1e1", s); y = (FPNum)ctx.mkNumeral("-1.25p3", s); FPExpr x_plus_y = (FPExpr)ctx.mkConst("x_plus_y", s); FPNum r = (FPNum)ctx.mkNumeral("100", s); slvr = ctx.mkSolver("QF_FP"); slvr.add(ctx.mkEq(x_plus_y, ctx.mkFPMul(ctx.mkFPRoundNearestTiesToAway(), x, y))); slvr.add(ctx.mkNot(ctx.mkFPEq(x_plus_y, r))); if (slvr.check() != Status.UNSATISFIABLE) throw new TestFailedException(); System.out.println("OK, unsat:" + System.getProperty("line.separator") + slvr); } public void floatingPointExample2(Context ctx) throws TestFailedException { System.out.println("FloatingPointExample2"); Log.append("FloatingPointExample2"); FPSort double_sort = ctx.mkFPSort(11, 53); FPRMSort rm_sort = ctx.mkFPRoundingModeSort(); FPRMExpr rm = (FPRMExpr)ctx.mkConst(ctx.mkSymbol("rm"), rm_sort); BitVecExpr x = (BitVecExpr)ctx.mkConst(ctx.mkSymbol("x"), ctx.mkBitVecSort(64)); FPExpr y = (FPExpr)ctx.mkConst(ctx.mkSymbol("y"), double_sort); FPExpr fp_val = ctx.mkFP(42, double_sort); BoolExpr c1 = ctx.mkEq(y, fp_val); BoolExpr c2 = ctx.mkEq(x, ctx.mkFPToBV(rm, y, 64, false)); BoolExpr c3 = ctx.mkEq(x, ctx.mkBV(42, 64)); BoolExpr c4 = ctx.mkEq(ctx.mkNumeral(42, ctx.getRealSort()), ctx.mkFPToReal(fp_val)); BoolExpr c5 = ctx.mkAnd(c1, c2, c3, c4); System.out.println("c5 = " + c5); /* Generic solver */ Solver s = ctx.mkSolver(); s.add(c5); if (s.check() != Status.SATISFIABLE) throw new TestFailedException(); System.out.println("OK, model: " + s.getModel().toString()); } public void optimizeExample(Context ctx) { System.out.println("Opt"); Optimize opt = ctx.mkOptimize(); // Set constraints. IntExpr xExp = ctx.mkIntConst("x"); IntExpr yExp = ctx.mkIntConst("y"); opt.Add(ctx.mkEq(ctx.mkAdd(xExp, yExp), ctx.mkInt(10)), ctx.mkGe(xExp, ctx.mkInt(0)), ctx.mkGe(yExp, ctx.mkInt(0))); // Set objectives. Optimize.Handle mx = opt.MkMaximize(xExp); Optimize.Handle my = opt.MkMaximize(yExp); System.out.println(opt.Check()); System.out.println(mx); System.out.println(my); } public void translationExample() { Context ctx1 = new Context(); Context ctx2 = new Context(); Sort s1 = ctx1.getIntSort(); Sort s2 = ctx2.getIntSort(); Sort s3 = (Sort) s1.translate(ctx2); System.out.println(s1 == s2); System.out.println(s1.equals(s2)); System.out.println(s2.equals(s3)); System.out.println(s1.equals(s3)); Expr e1 = ctx1.mkIntConst("e1"); Expr e2 = ctx2.mkIntConst("e1"); Expr e3 = e1.translate(ctx2); System.out.println(e1 == e2); System.out.println(e1.equals(e2)); System.out.println(e2.equals(e3)); System.out.println(e1.equals(e3)); } public static void main(String[] args) { JavaExample p = new JavaExample(); try { com.microsoft.z3.Global.ToggleWarningMessages(true); Log.open("test.log"); System.out.print("Z3 Major Version: "); System.out.println(Version.getMajor()); System.out.print("Z3 Full Version: "); System.out.println(Version.getString()); System.out.print("Z3 Full Version String: "); System.out.println(Version.getFullVersion()); p.simpleExample(); { // These examples need model generation turned on. HashMap cfg = new HashMap(); cfg.put("model", "true"); Context ctx = new Context(cfg); p.optimizeExample(ctx); p.basicTests(ctx); p.castingTest(ctx); p.sudokuExample(ctx); p.quantifierExample1(ctx); p.quantifierExample2(ctx); p.logicExample(ctx); p.parOrExample(ctx); p.findModelExample1(ctx); p.findModelExample2(ctx); p.pushPopExample1(ctx); p.arrayExample1(ctx); p.arrayExample3(ctx); p.bitvectorExample1(ctx); p.bitvectorExample2(ctx); p.parserExample1(ctx); p.parserExample2(ctx); p.parserExample4(ctx); p.parserExample5(ctx); p.iteExample(ctx); p.evalExample1(ctx); p.evalExample2(ctx); p.findSmallModelExample(ctx); p.simplifierExample(ctx); p.finiteDomainExample(ctx); p.floatingPointExample1(ctx); p.floatingPointExample2(ctx); } { // These examples need proof generation turned on. HashMap cfg = new HashMap(); cfg.put("proof", "true"); Context ctx = new Context(cfg); p.proveExample1(ctx); p.proveExample2(ctx); p.arrayExample2(ctx); p.tupleExample(ctx); p.parserExample3(ctx); p.enumExample(ctx); p.listExample(ctx); p.treeExample(ctx); p.forestExample(ctx); p.unsatCoreAndProofExample(ctx); p.unsatCoreAndProofExample2(ctx); } { // These examples need proof generation turned on and auto-config // set to false. HashMap cfg = new HashMap(); cfg.put("proof", "true"); cfg.put("auto-config", "false"); Context ctx = new Context(cfg); p.quantifierExample3(ctx); p.quantifierExample4(ctx); } p.translationExample(); Log.close(); if (Log.isOpen()) System.out.println("Log is still open!"); } catch (Z3Exception ex) { System.out.println("Z3 Managed Exception: " + ex.getMessage()); System.out.println("Stack trace: "); ex.printStackTrace(System.out); } catch (TestFailedException ex) { System.out.println("TEST CASE FAILED: " + ex.getMessage()); System.out.println("Stack trace: "); ex.printStackTrace(System.out); } catch (Exception ex) { System.out.println("Unknown Exception: " + ex.getMessage()); System.out.println("Stack trace: "); ex.printStackTrace(System.out); } } }