2021-10-01 18:21:02 -05:00
|
|
|
/******************************************************************************
|
|
|
|
|
* Top contributors (to current version):
|
2022-04-05 13:38:57 -07:00
|
|
|
* Mudathir Mohamed, Aina Niemetz, Andres Noetzli
|
2021-10-01 18:21:02 -05:00
|
|
|
*
|
|
|
|
|
* This file is part of the cvc5 project.
|
|
|
|
|
*
|
2022-04-05 13:38:57 -07:00
|
|
|
* Copyright (c) 2009-2022 by the authors listed in the file AUTHORS
|
2021-10-01 18:21:02 -05:00
|
|
|
* in the top-level source directory and their institutional affiliations.
|
|
|
|
|
* All rights reserved. See the file COPYING in the top-level source
|
|
|
|
|
* directory for licensing information.
|
|
|
|
|
* ****************************************************************************
|
|
|
|
|
*
|
|
|
|
|
* A simple demonstration of the api capabilities of cvc5.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2022-03-30 21:09:03 -07:00
|
|
|
import io.github.cvc5.*;
|
2021-10-01 18:21:02 -05:00
|
|
|
import java.math.BigInteger;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
public class QuickStart
|
|
|
|
|
{
|
|
|
|
|
public static void main(String args[]) throws CVC5ApiException
|
|
|
|
|
{
|
|
|
|
|
// Create a solver
|
2021-11-03 16:32:10 -05:00
|
|
|
try (Solver solver = new Solver())
|
2021-10-01 18:21:02 -05:00
|
|
|
{
|
2021-11-03 16:32:10 -05:00
|
|
|
// We will ask the solver to produce models and unsat cores,
|
|
|
|
|
// hence these options should be turned on.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-1 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.setOption("produce-models", "true");
|
|
|
|
|
solver.setOption("produce-unsat-cores", "true");
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-1 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// The simplest way to set a logic for the solver is to choose "ALL".
|
|
|
|
|
// This enables all logics in the solver.
|
|
|
|
|
// Alternatively, "QF_ALL" enables all logics without quantifiers.
|
|
|
|
|
// To optimize the solver's behavior for a more specific logic,
|
|
|
|
|
// use the logic name, e.g. "QF_BV" or "QF_AUFBV".
|
|
|
|
|
|
|
|
|
|
// Set the logic
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-2 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.setLogic("ALL");
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-2 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// In this example, we will define constraints over reals and integers.
|
|
|
|
|
// Hence, we first obtain the corresponding sorts.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-3 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
Sort realSort = solver.getRealSort();
|
|
|
|
|
Sort intSort = solver.getIntegerSort();
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-3 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// x and y will be real variables, while a and b will be integer variables.
|
|
|
|
|
// Formally, their cpp type is Term,
|
|
|
|
|
// and they are called "constants" in SMT jargon:
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-4 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
Term x = solver.mkConst(realSort, "x");
|
|
|
|
|
Term y = solver.mkConst(realSort, "y");
|
|
|
|
|
Term a = solver.mkConst(intSort, "a");
|
|
|
|
|
Term b = solver.mkConst(intSort, "b");
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-4 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// Our constraints regarding x and y will be:
|
|
|
|
|
//
|
|
|
|
|
// (1) 0 < x
|
|
|
|
|
// (2) 0 < y
|
|
|
|
|
// (3) x + y < 1
|
|
|
|
|
// (4) x <= y
|
|
|
|
|
//
|
|
|
|
|
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-5 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
// Formally, constraints are also terms. Their sort is Boolean.
|
|
|
|
|
// We will construct these constraints gradually,
|
|
|
|
|
// by defining each of their components.
|
|
|
|
|
// We start with the constant numerals 0 and 1:
|
|
|
|
|
Term zero = solver.mkReal(0);
|
|
|
|
|
Term one = solver.mkReal(1);
|
|
|
|
|
|
|
|
|
|
// Next, we construct the term x + y
|
2022-02-02 20:25:14 -08:00
|
|
|
Term xPlusY = solver.mkTerm(Kind.ADD, x, y);
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// Now we can define the constraints.
|
|
|
|
|
// They use the operators +, <=, and <.
|
2022-02-02 20:25:14 -08:00
|
|
|
// In the API, these are denoted by ADD, LEQ, and LT.
|
2021-11-03 16:32:10 -05:00
|
|
|
// A list of available operators is available in:
|
|
|
|
|
// src/api/cpp/cvc5_kind.h
|
|
|
|
|
Term constraint1 = solver.mkTerm(Kind.LT, zero, x);
|
|
|
|
|
Term constraint2 = solver.mkTerm(Kind.LT, zero, y);
|
|
|
|
|
Term constraint3 = solver.mkTerm(Kind.LT, xPlusY, one);
|
|
|
|
|
Term constraint4 = solver.mkTerm(Kind.LEQ, x, y);
|
|
|
|
|
|
|
|
|
|
// Now we assert the constraints to the solver.
|
|
|
|
|
solver.assertFormula(constraint1);
|
|
|
|
|
solver.assertFormula(constraint2);
|
|
|
|
|
solver.assertFormula(constraint3);
|
|
|
|
|
solver.assertFormula(constraint4);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-5 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// Check if the formula is satisfiable, that is,
|
|
|
|
|
// are there real values for x and y that satisfy all the constraints?
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-6 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
Result r1 = solver.checkSat();
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-6 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// The result is either SAT, UNSAT, or UNKNOWN.
|
|
|
|
|
// In this case, it is SAT.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-7 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
System.out.println("expected: sat");
|
|
|
|
|
System.out.println("result: " + r1);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-7 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// We can get the values for x and y that satisfy the constraints.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-8 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
Term xVal = solver.getValue(x);
|
|
|
|
|
Term yVal = solver.getValue(y);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-8 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// It is also possible to get values for compound terms,
|
|
|
|
|
// even if those did not appear in the original formula.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-9 start]
|
2022-02-02 18:18:51 -08:00
|
|
|
Term xMinusY = solver.mkTerm(Kind.SUB, x, y);
|
2021-11-03 16:32:10 -05:00
|
|
|
Term xMinusYVal = solver.getValue(xMinusY);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-9 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
2021-12-06 19:31:47 -06:00
|
|
|
// Further, we can convert the values to java types
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-10 start]
|
2021-12-06 19:31:47 -06:00
|
|
|
Pair<BigInteger, BigInteger> xPair = xVal.getRealValue();
|
|
|
|
|
Pair<BigInteger, BigInteger> yPair = yVal.getRealValue();
|
|
|
|
|
Pair<BigInteger, BigInteger> xMinusYPair = xMinusYVal.getRealValue();
|
|
|
|
|
|
|
|
|
|
System.out.println("value for x: " + xPair.first + "/" + xPair.second);
|
|
|
|
|
System.out.println("value for y: " + yPair.first + "/" + yPair.second);
|
|
|
|
|
System.out.println("value for x - y: " + xMinusYPair.first + "/" + xMinusYPair.second);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-10 end]
|
2021-12-06 19:31:47 -06:00
|
|
|
|
|
|
|
|
// Another way to independently compute the value of x - y would be
|
|
|
|
|
// to perform the (rational) arithmetic manually.
|
|
|
|
|
// However, for more complex terms,
|
|
|
|
|
// it is easier to let the solver do the evaluation.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-11 start]
|
2021-12-06 19:31:47 -06:00
|
|
|
Pair<BigInteger, BigInteger> xMinusYComputed =
|
|
|
|
|
new Pair(xPair.first.multiply(yPair.second).subtract(xPair.second.multiply(yPair.first)),
|
|
|
|
|
xPair.second.multiply(yPair.second));
|
|
|
|
|
BigInteger g = xMinusYComputed.first.gcd(xMinusYComputed.second);
|
|
|
|
|
xMinusYComputed = new Pair(xMinusYComputed.first.divide(g), xMinusYComputed.second.divide(g));
|
|
|
|
|
if (xMinusYComputed.equals(xMinusYPair))
|
|
|
|
|
{
|
|
|
|
|
System.out.println("computed correctly");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
System.out.println("computed incorrectly");
|
|
|
|
|
}
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-11 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// Next, we will check satisfiability of the same formula,
|
|
|
|
|
// only this time over integer variables a and b.
|
|
|
|
|
|
|
|
|
|
// We start by resetting assertions added to the solver.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-12 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.resetAssertions();
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-12 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// Next, we assert the same assertions above with integers.
|
|
|
|
|
// This time, we inline the construction of terms
|
|
|
|
|
// to the assertion command.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-13 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.assertFormula(solver.mkTerm(Kind.LT, solver.mkInteger(0), a));
|
|
|
|
|
solver.assertFormula(solver.mkTerm(Kind.LT, solver.mkInteger(0), b));
|
|
|
|
|
solver.assertFormula(
|
2022-02-02 20:25:14 -08:00
|
|
|
solver.mkTerm(Kind.LT, solver.mkTerm(Kind.ADD, a, b), solver.mkInteger(1)));
|
2021-11-03 16:32:10 -05:00
|
|
|
solver.assertFormula(solver.mkTerm(Kind.LEQ, a, b));
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-13 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// We check whether the revised assertion is satisfiable.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-14 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
Result r2 = solver.checkSat();
|
|
|
|
|
|
|
|
|
|
// This time the formula is unsatisfiable
|
|
|
|
|
System.out.println("expected: unsat");
|
|
|
|
|
System.out.println("result: " + r2);
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-14 end]
|
2021-11-03 16:32:10 -05:00
|
|
|
|
|
|
|
|
// We can query the solver for an unsatisfiable core, i.e., a subset
|
|
|
|
|
// of the assertions that is already unsatisfiable.
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-15 start]
|
2021-11-03 16:32:10 -05:00
|
|
|
List<Term> unsatCore = Arrays.asList(solver.getUnsatCore());
|
|
|
|
|
System.out.println("unsat core size: " + unsatCore.size());
|
|
|
|
|
System.out.println("unsat core: ");
|
|
|
|
|
for (Term t : unsatCore)
|
|
|
|
|
{
|
|
|
|
|
System.out.println(t);
|
|
|
|
|
}
|
2022-05-02 13:13:00 -07:00
|
|
|
//! [docs-java-quickstart-15 end]
|
2021-10-01 18:21:02 -05:00
|
|
|
}
|
|
|
|
|
}
|
2022-05-02 13:13:00 -07:00
|
|
|
}
|