Quickstart Guide

First, 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, but not actual values.

    x, y = Reals('x y')
    a, b = Ints('a b')

We define the following constraints regarding x and y :

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

We check whether there is a solution to these constraints:

    solve(0 < x, 0 < y, x + y < 1, x <= y)

In this case, there is, so we get output:

[x = 1/6, y = 1/6]

We can also get an explicit model (assignment) for the constraints.

    s = Solver()
    s.add(0 < x, 0 < y, x + y < 1, x <= y)
    assert sat == s.check()
    m = s.model()

With the model, we can evaluate variables and terms:

    print('x:', m[x])
    print('y:', m[y])
    print('x - y:', m[x - y])

This will print:

x: 1/6
y: 1/6
x - y: 0

We can also get these values in other forms:

    print('string x:', str(m[x]))
    print('decimal x:', m[x].as_decimal(4))
    print('fraction x:', m[x].as_fraction())
    print('float x:', float(m[x].as_fraction()))

Next, we assert the same assertions as above, but with integers. This time, there is no solution, so “no solution” is printed.

    solve(0 < a, 0 < b, a + b < 1, a <= b)

Example

examples/api/python/quickstart.py

  1 #!/usr/bin/env python
  2 ###############################################################################
  3 # Top contributors (to current version):
  4 #   Yoni Zohar, Aina Niemetz, Alex Ozdemir
  5 #
  6 # This file is part of the cvc5 project.
  7 #
  8 # Copyright (c) 2009-2022 by the authors listed in the file AUTHORS
  9 # in the top-level source directory and their institutional affiliations.
 10 # All rights reserved.  See the file COPYING in the top-level source
 11 # directory for licensing information.
 12 # #############################################################################
 13 #
 14 # A simple demonstration of the api capabilities of cvc5, adapted from quickstart.cpp
 15 ##
 16 
 17 import cvc5
 18 from cvc5 import Kind
 19 
 20 if __name__ == "__main__":
 21   # Create a solver
 22   solver = cvc5.Solver()
 23 
 24   # We will ask the solver to produce models and unsat cores,
 25   # hence these options should be turned on.
 26   solver.setOption("produce-models", "true");
 27   solver.setOption("produce-unsat-cores", "true");
 28 
 29   # The simplest way to set a logic for the solver is to choose "ALL".
 30   # This enables all logics in the solver.
 31   # Alternatively, "QF_ALL" enables all logics without quantifiers.
 32   # To optimize the solver's behavior for a more specific logic,
 33   # use the logic name, e.g. "QF_BV" or "QF_AUFBV".
 34 
 35   # Set the logic
 36   solver.setLogic("ALL");
 37 
 38   # In this example, we will define constraints over reals and integers.
 39   # Hence, we first obtain the corresponding sorts.
 40   realSort = solver.getRealSort();
 41   intSort = solver.getIntegerSort();
 42 
 43   # x and y will be real variables, while a and b will be integer variables.
 44   # Formally, their python type is Term,
 45   # and they are called "constants" in SMT jargon:
 46   x = solver.mkConst(realSort, "x");
 47   y = solver.mkConst(realSort, "y");
 48   a = solver.mkConst(intSort, "a");
 49   b = solver.mkConst(intSort, "b");
 50 
 51   # Our constraints regarding x and y will be:
 52   #
 53   #   (1)  0 < x
 54   #   (2)  0 < y
 55   #   (3)  x + y < 1
 56   #   (4)  x <= y
 57   #
 58 
 59   # Formally, constraints are also terms. Their sort is Boolean.
 60   # We will construct these constraints gradually,
 61   # by defining each of their components.
 62   # We start with the constant numerals 0 and 1:
 63   zero = solver.mkReal(0);
 64   one = solver.mkReal(1);
 65 
 66   # Next, we construct the term x + y
 67   xPlusY = solver.mkTerm(Kind.ADD, x, y);
 68 
 69   # Now we can define the constraints.
 70   # They use the operators +, <=, and <.
 71   # In the API, these are denoted by Plus, Leq, and Lt.
 72   constraint1 = solver.mkTerm(Kind.LT, zero, x);
 73   constraint2 = solver.mkTerm(Kind.LT, zero, y);
 74   constraint3 = solver.mkTerm(Kind.LT, xPlusY, one);
 75   constraint4 = solver.mkTerm(Kind.LEQ, x, y);
 76 
 77   # Now we assert the constraints to the solver.
 78   solver.assertFormula(constraint1);
 79   solver.assertFormula(constraint2);
 80   solver.assertFormula(constraint3);
 81   solver.assertFormula(constraint4);
 82 
 83   # Check if the formula is satisfiable, that is,
 84   # are there real values for x and y that satisfy all the constraints?
 85   r1 = solver.checkSat();
 86 
 87   # The result is either SAT, UNSAT, or UNKNOWN.
 88   # In this case, it is SAT.
 89   print("expected: sat")
 90   print("result: ", r1)
 91 
 92   # We can get the values for x and y that satisfy the constraints.
 93   xVal = solver.getValue(x);
 94   yVal = solver.getValue(y);
 95 
 96   # It is also possible to get values for compound terms,
 97   # even if those did not appear in the original formula.
 98   xMinusY = solver.mkTerm(Kind.SUB, x, y);
 99   xMinusYVal = solver.getValue(xMinusY);
100   
101   # We can now obtain the values as python values
102   xPy = xVal.getRealValue();
103   yPy = yVal.getRealValue();
104   xMinusYPy = xMinusYVal.getRealValue();
105 
106   print("value for x: ", xPy)
107   print("value for y: ", yPy)
108   print("value for x - y: ", xMinusYPy)
109 
110   # Another way to independently compute the value of x - y would be
111   # to use the python minus operator instead of asking the solver.
112   # However, for more complex terms,
113   # it is easier to let the solver do the evaluation.
114   xMinusYComputed = xPy - yPy;
115   if xMinusYComputed == xMinusYPy:
116     print("computed correctly") 
117   else:
118     print("computed incorrectly")
119 
120   # Further, we can convert the values to strings
121   xStr = str(xPy);
122   yStr = str(yPy);
123   xMinusYStr = str(xMinusYPy);
124 
125 
126   # Next, we will check satisfiability of the same formula,
127   # only this time over integer variables a and b.
128 
129   # We start by resetting assertions added to the solver.
130   solver.resetAssertions();
131 
132   # Next, we assert the same assertions above with integers.
133   # This time, we inline the construction of terms
134   # to the assertion command.
135   solver.assertFormula(solver.mkTerm(Kind.LT, solver.mkInteger(0), a));
136   solver.assertFormula(solver.mkTerm(Kind.LT, solver.mkInteger(0), b));
137   solver.assertFormula(
138       solver.mkTerm(
139           Kind.LT, solver.mkTerm(Kind.ADD, a, b), solver.mkInteger(1)));
140   solver.assertFormula(solver.mkTerm(Kind.LEQ, a, b));
141 
142   # We check whether the revised assertion is satisfiable.
143   r2 = solver.checkSat();
144 
145   # This time the formula is unsatisfiable
146   print("expected: unsat")
147   print("result:", r2)
148 
149   # We can query the solver for an unsatisfiable core, i.e., a subset
150   # of the assertions that is already unsatisfiable.
151   unsatCore = solver.getUnsatCore();
152   print("unsat core size:", len(unsatCore))
153   print("unsat core:", unsatCore)