Quickstart Guide

First, create a cvc5 TermManager instance:

rmManager tm = new TermManager();

Then, create a cvc5 Solver instance:

lver solver = new Solver(tm);

To produce models and unsat cores, we have to enable the following options.

solver.setOption("produce-models", "true");
solver.setOption("produce-unsat-cores", "true");

Next we set the logic. 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".

solver.setLogic("ALL");

In the following, we will define real and integer constraints. For this, we first query the solver for the corresponding sorts.

Sort realSort = tm.getRealSort();
Sort intSort = tm.getIntegerSort();

Now, we create two constants x and y of sort Real, and two constants a and b of sort Integer. Notice that these are symbolic constants, not actual values.

Term x = tm.mkConst(realSort, "x");
Term y = tm.mkConst(realSort, "y");
Term a = tm.mkConst(intSort, "a");
Term b = tm.mkConst(intSort, "b");

We define the following constraints regarding x and y:

\[(0 < x) \wedge (0 < y) \wedge (x + y < 1) \wedge (x \leq y)\]

We construct the required terms and assert them as follows:

// 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 = tm.mkReal(0);
Term one = tm.mkReal(1);

// Next, we construct the term x + y
Term xPlusY = tm.mkTerm(Kind.ADD, x, y);

// Now we can define the constraints.
// They use the operators +, <=, and <.
// In the API, these are denoted by ADD, LEQ, and LT.
// A list of available operators is available in:
// src/api/cpp/cvc5_kind.h
Term constraint1 = tm.mkTerm(Kind.LT, zero, x);
Term constraint2 = tm.mkTerm(Kind.LT, zero, y);
Term constraint3 = tm.mkTerm(Kind.LT, xPlusY, one);
Term constraint4 = tm.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);

Now we check if the asserted formula is satisfiable, that is, we check if there exist values of sort Real for x and y that satisfy all the constraints.

Result r1 = solver.checkSat();

The result we get from this satisfiability check is either sat, unsat or unknown. It’s status can be queried via Result.isSat, Result.isUnsat and Result.isSatUnknown. Alternatively, it can also be printed.

System.out.println("expected: sat");
System.out.println("result: " + r1);

This will print:

expected: sat
result: sat

Now, we query the solver for the values for x and y that satisfy the constraints.

Term xVal = solver.getValue(x);
Term yVal = solver.getValue(y);

It is also possible to get values for terms that do not appear in the original formula.

Term xMinusY = tm.mkTerm(Kind.SUB, x, y);
Term xMinusYVal = solver.getValue(xMinusY);

We can convert these values to Java types.

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);

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.

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");
}

This will print:

computed correctly

Next, we will check satisfiability of the same formula, only this time over integer variables a and b. For this, we first reset the assertions added to the solver.

solver.resetAssertions();

Next, we assert the same assertions as above, but with integers. This time, we inline the construction of terms in the assertion command.

solver.assertFormula(tm.mkTerm(Kind.LT, tm.mkInteger(0), a));
solver.assertFormula(tm.mkTerm(Kind.LT, tm.mkInteger(0), b));
solver.assertFormula(
    tm.mkTerm(Kind.LT, tm.mkTerm(Kind.ADD, a, b), tm.mkInteger(1)));
solver.assertFormula(tm.mkTerm(Kind.LEQ, a, b));

Now, we check whether the revised assertion is satisfiable.

Result r2 = solver.checkSat();

// This time the formula is unsatisfiable
System.out.println("expected: unsat");
System.out.println("result: " + r2);

This time the asserted formula is unsatisfiable:

expected: unsat
result: unsat

We can query the solver for an unsatisfiable core, that is, a subset of the assertions that is already unsatisfiable.

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);
}

This will print:

unsat core size: 3
unsat core:
(< 0 a)
(< 0 b)
(< (+ a b) 1)

Example

examples/api/java/QuickStart.java

  1/******************************************************************************
  2 * Top contributors (to current version):
  3 *   Mudathir Mohamed, Aina Niemetz, Andres Noetzli
  4 *
  5 * This file is part of the cvc5 project.
  6 *
  7 * Copyright (c) 2009-2024 by the authors listed in the file AUTHORS
  8 * in the top-level source directory and their institutional affiliations.
  9 * All rights reserved.  See the file COPYING in the top-level source
 10 * directory for licensing information.
 11 * ****************************************************************************
 12 *
 13 * A simple demonstration of the api capabilities of cvc5.
 14 *
 15 */
 16
 17import io.github.cvc5.*;
 18import java.math.BigInteger;
 19import java.util.ArrayList;
 20import java.util.Arrays;
 21import java.util.List;
 22
 23public class QuickStart
 24{
 25  public static void main(String args[]) throws CVC5ApiException
 26  {
 27    // Create a term manager
 28    //! [docs-java-quickstart-0 start]
 29    TermManager tm = new TermManager();
 30    //! [docs-java-quickstart-0 end]
 31    // Create a solver
 32    //! [docs-java-quickstart-1 start]
 33    Solver solver = new Solver(tm);
 34    //! [docs-java-quickstart-1 end]
 35    {
 36      // We will ask the solver to produce models and unsat cores,
 37      // hence these options should be turned on.
 38      //! [docs-java-quickstart-2 start]
 39      solver.setOption("produce-models", "true");
 40      solver.setOption("produce-unsat-cores", "true");
 41      //! [docs-java-quickstart-2 end]
 42
 43      // The simplest way to set a logic for the solver is to choose "ALL".
 44      // This enables all logics in the solver.
 45      // Alternatively, "QF_ALL" enables all logics without quantifiers.
 46      // To optimize the solver's behavior for a more specific logic,
 47      // use the logic name, e.g. "QF_BV" or "QF_AUFBV".
 48
 49      // Set the logic
 50      //! [docs-java-quickstart-3 start]
 51      solver.setLogic("ALL");
 52      //! [docs-java-quickstart-3 end]
 53
 54      // In this example, we will define constraints over reals and integers.
 55      // Hence, we first obtain the corresponding sorts.
 56      //! [docs-java-quickstart-4 start]
 57      Sort realSort = tm.getRealSort();
 58      Sort intSort = tm.getIntegerSort();
 59      //! [docs-java-quickstart-4 end]
 60
 61      // x and y will be real variables, while a and b will be integer variables.
 62      // Formally, their cpp type is Term,
 63      // and they are called "constants" in SMT jargon:
 64      //! [docs-java-quickstart-5 start]
 65      Term x = tm.mkConst(realSort, "x");
 66      Term y = tm.mkConst(realSort, "y");
 67      Term a = tm.mkConst(intSort, "a");
 68      Term b = tm.mkConst(intSort, "b");
 69      //! [docs-java-quickstart-5 end]
 70
 71      // Our constraints regarding x and y will be:
 72      //
 73      //   (1)  0 < x
 74      //   (2)  0 < y
 75      //   (3)  x + y < 1
 76      //   (4)  x <= y
 77      //
 78
 79      //! [docs-java-quickstart-6 start]
 80      // Formally, constraints are also terms. Their sort is Boolean.
 81      // We will construct these constraints gradually,
 82      // by defining each of their components.
 83      // We start with the constant numerals 0 and 1:
 84      Term zero = tm.mkReal(0);
 85      Term one = tm.mkReal(1);
 86
 87      // Next, we construct the term x + y
 88      Term xPlusY = tm.mkTerm(Kind.ADD, x, y);
 89
 90      // Now we can define the constraints.
 91      // They use the operators +, <=, and <.
 92      // In the API, these are denoted by ADD, LEQ, and LT.
 93      // A list of available operators is available in:
 94      // src/api/cpp/cvc5_kind.h
 95      Term constraint1 = tm.mkTerm(Kind.LT, zero, x);
 96      Term constraint2 = tm.mkTerm(Kind.LT, zero, y);
 97      Term constraint3 = tm.mkTerm(Kind.LT, xPlusY, one);
 98      Term constraint4 = tm.mkTerm(Kind.LEQ, x, y);
 99
100      // Now we assert the constraints to the solver.
101      solver.assertFormula(constraint1);
102      solver.assertFormula(constraint2);
103      solver.assertFormula(constraint3);
104      solver.assertFormula(constraint4);
105      //! [docs-java-quickstart-6 end]
106
107      // Check if the formula is satisfiable, that is,
108      // are there real values for x and y that satisfy all the constraints?
109      //! [docs-java-quickstart-7 start]
110      Result r1 = solver.checkSat();
111      //! [docs-java-quickstart-7 end]
112
113      // The result is either SAT, UNSAT, or UNKNOWN.
114      // In this case, it is SAT.
115      //! [docs-java-quickstart-8 start]
116      System.out.println("expected: sat");
117      System.out.println("result: " + r1);
118      //! [docs-java-quickstart-8 end]
119
120      // We can get the values for x and y that satisfy the constraints.
121      //! [docs-java-quickstart-9 start]
122      Term xVal = solver.getValue(x);
123      Term yVal = solver.getValue(y);
124      //! [docs-java-quickstart-9 end]
125
126      // It is also possible to get values for compound terms,
127      // even if those did not appear in the original formula.
128      //! [docs-java-quickstart-10 start]
129      Term xMinusY = tm.mkTerm(Kind.SUB, x, y);
130      Term xMinusYVal = solver.getValue(xMinusY);
131      //! [docs-java-quickstart-10 end]
132
133      // Further, we can convert the values to java types
134      //! [docs-java-quickstart-11 start]
135      Pair<BigInteger, BigInteger> xPair = xVal.getRealValue();
136      Pair<BigInteger, BigInteger> yPair = yVal.getRealValue();
137      Pair<BigInteger, BigInteger> xMinusYPair = xMinusYVal.getRealValue();
138
139      System.out.println("value for x: " + xPair.first + "/" + xPair.second);
140      System.out.println("value for y: " + yPair.first + "/" + yPair.second);
141      System.out.println("value for x - y: " + xMinusYPair.first + "/" + xMinusYPair.second);
142      //! [docs-java-quickstart-11 end]
143
144      // Another way to independently compute the value of x - y would be
145      // to perform the (rational) arithmetic manually.
146      // However, for more complex terms,
147      // it is easier to let the solver do the evaluation.
148      //! [docs-java-quickstart-12 start]
149      Pair<BigInteger, BigInteger> xMinusYComputed =
150          new Pair<>(xPair.first.multiply(yPair.second).subtract(xPair.second.multiply(yPair.first)),
151              xPair.second.multiply(yPair.second));
152      BigInteger g = xMinusYComputed.first.gcd(xMinusYComputed.second);
153      xMinusYComputed = new Pair<>(xMinusYComputed.first.divide(g), xMinusYComputed.second.divide(g));
154      if (xMinusYComputed.equals(xMinusYPair))
155      {
156        System.out.println("computed correctly");
157      }
158      else
159      {
160        System.out.println("computed incorrectly");
161      }
162      //! [docs-java-quickstart-12 end]
163
164      // Next, we will check satisfiability of the same formula,
165      // only this time over integer variables a and b.
166
167      // We start by resetting assertions added to the solver.
168      //! [docs-java-quickstart-13 start]
169      solver.resetAssertions();
170      //! [docs-java-quickstart-13 end]
171
172      // Next, we assert the same assertions above with integers.
173      // This time, we inline the construction of terms
174      // to the assertion command.
175      //! [docs-java-quickstart-14 start]
176      solver.assertFormula(tm.mkTerm(Kind.LT, tm.mkInteger(0), a));
177      solver.assertFormula(tm.mkTerm(Kind.LT, tm.mkInteger(0), b));
178      solver.assertFormula(
179          tm.mkTerm(Kind.LT, tm.mkTerm(Kind.ADD, a, b), tm.mkInteger(1)));
180      solver.assertFormula(tm.mkTerm(Kind.LEQ, a, b));
181      //! [docs-java-quickstart-14 end]
182
183      // We check whether the revised assertion is satisfiable.
184      //! [docs-java-quickstart-15 start]
185      Result r2 = solver.checkSat();
186
187      // This time the formula is unsatisfiable
188      System.out.println("expected: unsat");
189      System.out.println("result: " + r2);
190      //! [docs-java-quickstart-15 end]
191
192      // We can query the solver for an unsatisfiable core, i.e., a subset
193      // of the assertions that is already unsatisfiable.
194      //! [docs-java-quickstart-16 start]
195      List<Term> unsatCore = Arrays.asList(solver.getUnsatCore());
196      System.out.println("unsat core size: " + unsatCore.size());
197      System.out.println("unsat core: ");
198      for (Term t : unsatCore)
199      {
200        System.out.println(t);
201      }
202      //! [docs-java-quickstart-16 end]
203    }
204    Context.deletePointers();
205  }
206}