Python API Documentation

Quickstart

First, create a TermManager instance that allows us to create sorts and terms later:

    tm = TermManager()

Then, create a bitwuzla.Options instance:

    options = Options()

This instance can be configured via bitwuzla.Options.set(). For example, to enable model generation (SMT-LIB: (set-option :produce-models true)):

    options.set(Option.PRODUCE_MODELS, True)

Some options have modes, which can be configured via the string representation of their modes. For example, to enable CaDiCaL as back end SAT solver (this is for illustration purposes only, CaDiCaL is configured by default):

    options.set(Option.SAT_SOLVER, 'cadical')

For more details on available options, see Options.

Then, create a bitwuzla.Bitwuzla solver instance with a term manager and configured options(configuration options are now frozen and cannot be changed for this instance):

    bitwuzla = Bitwuzla(tm, options)

Next, you will want to create some expressions via the term manager tm and assert formulas.

Note

Sorts and terms can be shared between multiple solver instances as long as these solvers use the same term manager.

For example, consider the following SMT-LIB input:

(set-logic QF_ABV)
(set-option :produce-models true)
(declare-const x (_ BitVec 8))
(declare-const y (_ BitVec 8))
(declare-fun f ((_ BitVec 8) (_ BitVec 4)) (_ BitVec 8))
(declare-const a (Array (_ BitVec 8) (_ BitVec 8)))
(assert
    (distinct
        ((_ extract 3 0) (bvsdiv x (_ bv2 8)))
        ((_ extract 3 0) (bvashr y (_ bv1 8)))))
(assert (= (f x ((_ extract 6 3) x)) y))
(assert (= (select a x) y))
(check-sat)
(get-model)
(get-value (x y f a (bvmul x x)))
(exit)

This input is created and asserted as follows:

    # First, create a term manager instance.
    tm = TermManager()
    # Create a Bitwuzla options instance.
    options = Options()
    # Then, enable model generation.
    options.set(Option.PRODUCE_MODELS, True)
    # Now, for illustration purposes, we enable CaDiCaL as SAT solver
    # (CaDiCaL is already configured by default).
    # Note: This will silently fall back to one of the compiled in SAT solvers
    #       if the selected solver is not compiled in.
    options.set(Option.SAT_SOLVER, 'cadical')
    # Then, create a Bitwuzla instance.
    bitwuzla = Bitwuzla(tm, options)

    # Create bit-vector sorts of size 4 and 8.
    sortbv4 = tm.mk_bv_sort(4)
    sortbv8 = tm.mk_bv_sort(8)
    # Create function sort.
    sortfun = tm.mk_fun_sort([sortbv8, sortbv4], sortbv8)
    # Create array sort.
    sortarr = tm.mk_array_sort(sortbv8, sortbv8)

    # Create two bit-vector constants of that sort.
    x = tm.mk_const(sortbv8, "x")
    y = tm.mk_const(sortbv8, "y")
    # Create fun const.
    f = tm.mk_const(sortfun, "f")
    # Create array const.
    a = tm.mk_const(sortarr, "a")
    # Create bit-vector values one and two of the same sort.
    one = tm.mk_bv_one(sortbv8)
    # Alternatively, you can create bit-vector value one with:
    # one = tm.mk_bv_value(sortbv8, "1", 2)
    # one = tm.mk_bv_value(sortbv8, 1)
    two = tm.mk_bv_value(sortbv8, 2)

    # (bvsdiv x (_ bv2 8))
    sdiv = tm.mk_term(Kind.BV_SDIV, [x, two])
    # (bvashr y (_ bv1 8))
    ashr = tm.mk_term(Kind.BV_ASHR, [y, one])
    # ((_ extract 3 0) (bvsdiv x (_ bv2 8)))
    sdive = tm.mk_term(Kind.BV_EXTRACT, [sdiv], [3, 0])
    # ((_ extract 3 0) (bvashr x (_ bv1 8)))
    ashre = tm.mk_term(Kind.BV_EXTRACT, [ashr], [3, 0])

    # (assert
    #     (distinct
    #         ((_ extract 3 0) (bvsdiv x (_ bv2 8)))
    #         ((_ extract 3 0) (bvashr y (_ bv1 8)))))
    bitwuzla.assert_formula(tm.mk_term(Kind.DISTINCT, [sdive, ashre]))
    # (assert (= (f x ((_ extract 6 3) x)) y))
    bitwuzla.assert_formula(tm.mk_term(
        Kind.EQUAL,
        [tm.mk_term(Kind.APPLY, [f, x, tm.mk_term(Kind.BV_EXTRACT, [x], [6, 3])]),
         y]))
    # (assert (= (select a x) y))
    bitwuzla.assert_formula(
        tm.mk_term(Kind.EQUAL, [tm.mk_term(Kind.ARRAY_SELECT, [a, x]), y]))

Alternatively, you can parse an input file in BTOR2 format [NPWB18] or SMT-LIB v2 format [BFT17] by creating a parser bitwuzla.Parser and then parsing the input file via bitwuzla.Parser.parse().

Note

The input parser creates a bitwuzla.Bitwuzla instance, which can be configured via the bitwuzla.Options instance passed into the parser. This Bitwuzla instance can be retrieved via bitwuzla.Parser.bitwuzla().

For example, to parse an example file examples/smt2/quickstart.smt2 in SMT-LIB format:

    tm = TermManager()
    options = Options()
    # We will parse example file `smt2/quickstart.smt2`.
    # Create parser instance.
    parser = Parser(tm, options)
    res = parser.parse("../smt2/quickstart.smt2")
    assert not res

Note

If the input is given in SMT-LIB format, commands like check-sat or get-value will be executed while parsing if argument parse_only is passed into bitwuzla.Parser.parse() as True.

After parsing from an input file, the parsed assertions can be retrieved via bitwuzla.Bitwuzla.get_assertions():

    # Now we retrieve the set of asserted formulas and print them.
    assertions = parser.bitwuzla().get_assertions()
    print('Assertions:')
    print('{')
    for a in assertions:
        print(f' {a}')
    print('}')

Alternatively, Bitwuzla also supports parsing from strings via bitwuzla.Parser.parse(). The quickstart input above can be parsed as one huge input string, or any its subsets of commands.

Bitwuzla also allows to add onto input parsed from a file. For example, after parsing in examples/smt2/quickstart.smt2, which is satisfiable, we add an assertion (which now makes the input formula unsatisfiable) via parsing from string as follows:

    parser.parse('(assert (distinct (select a x) y))', True, False)

Bitwuzla also supports parsing terms and sorts from strings via bitwuzla.Parser.parse_term() and bitwuzla.Parser.parse_sort().

Note

Declarations like declare-const are commands (not terms) in the SMT-LIB language. Commands must be parsed in via bitwuzla.Parser.parse(). Function bitwuzla.Parser.parse_term() and bitwuzla.Parser.parse_sort() only support parsing SMT-LIB terms and sorts, respectively.

For example, to parse a bit-vector sort of size 16 from string and show that it corresponds to the bit-vector sort of size 16 created via bitwuzla.mk_bv_sort():

    # Declare bit-vector sort of size 16.
    bv16 = parser.parse_sort('(_ BitVec 16)')
    # Create bit-vector sort of size 16 and show that it corresponds to
    # its string representation '(_ BitVec16)'.
    assert bv16 == tm.mk_bv_sort(16)

Then, to declare Boolean constants c and d and a bit-vector constant b:

    parser.parse("(declare-const c Bool)(declare-const d Bool)", True, False)
    parser.parse('(declare-const b (_ BitVec 16))', True, False)

These terms can be retrieved via bitwuzla.Parser.parse_term():

    # Retrieve term representing 'b'.
    b = parser.parse_term('b')
    # Retrieve term representing 'c'.
    c = parser.parse_term('c')
    # Retrieve term representing 'd'.
    d = parser.parse_term('d')

Now, to parse in terms using these constants via bitwuzla.Parser.parse_term():

    # Create xor over 'c' and 'd' and show that it corresponds to term
    # parsed in from its string representation '(xor c d)'.
    assert parser.parse_term('(xor c d)') == tm.mk_term(Kind.XOR, [c, d])
    # Create bit-vector addition over 'b' and bit-vector value
    # '1011111010001010' and show that it corresponds to the term parsed in
    # from its string representation '(bvadd b #b1011111010001010)'.
    assert parser.parse_term('(bvadd b #b1011111010001010)') \
           == tm.mk_term(Kind.BV_ADD,
                      [b, tm.mk_bv_value(bv16, '1011111010001010', 2)])

After parsing input and asserting formulas, satisfiability can be determined via bitwuzla.Bitwuzla.check_sat().

    # (check-sat)
    result = bitwuzla.check_sat()

Formulas can also be assumed via passing a vector of assumptions into bitwuzla.Bitwuzla.check_sat().

If the formula is satisfiable and model generation has been enabled, the resulting model can be printed via bitwuzla.Bitwuzla.get_value() and bitwuzla.Term.str(). An example implementation illustrating how to print the current model via declared symbols (in this case x, y, f and a) is below:

    # Print model in SMT-LIBv2 format.
    print('Model:\n(')
    for term in [x, y, f, a]:
        sort = term.sort()
        symbol = term.symbol()
        print(f'  (define-fun {symbol if symbol else "@t" + term.id()} (',
              end = '')
        if sort.is_fun():
            value = bitwuzla.get_value(term)
            assert value.kind() == Kind.LAMBDA
            assert value.num_children() == 2
            while value[1].kind() == Kind.LAMBDA:
                assert value[0].is_variable()
                print(f'({value[0]} {value[0].sort()}) ',
                      end = '')
                value = value[1]
            assert value[0].is_variable()
            print(f'({value[0]} {value[0].sort()})) ' \
                  + f'{sort.fun_codomain()} {value[1]})')
        else:
            print(f') {sort} {bitwuzla.get_value(term)})')
    print(')')
    print()

This will output a possible model, in this case:

(
  (define-fun x () (_ BitVec 8) #b10011111)
  (define-fun y () (_ BitVec 8) #b11111111)
  (define-fun f ((@bzla.var_74 (_ BitVec 8))  (@bzla.var_75 (_ BitVec 4))) (_ BitVec 8) (ite (and (= @bzla.var_74 #b10011111) (= @bzla.var_75 #b0011)) #b11111111 #b00000000))
  (define-fun a () (Array (_ BitVec 8) (_ BitVec 8)) (store ((as const (Array (_ BitVec 8) (_ BitVec 8))) #b00000000) #b10011111 #b11111111))
)

Alternatively, it is possible to query the value of terms as a term via bitwuzla.Bitwuzla.get_value(); or as assignment via bitwuzla.Term.value(), which returns the string representation of bit-vector and floating-point values, the bitwuzla.RoundingMode value for RoundingMode values, and a bool value for Boolean values.

Additionally, for floating-point values, bitwuzla.Term.value() allows to retrieve the assignment split into assignment strings for the sign bit, the exponent and the significand.

In our case, we can query the assignments of x and y, both bit-vector terms, as binary strings:

    # Both x and y are bit-vector terms and their value is a bit-vector
    # value that can be printed via Term.value().
    print(f'value of x: {bitwuzla.get_value(x).value(2)}')
    print(f'value of y: {bitwuzla.get_value(y).value(2)}')

This will print:

value of x: 10011111
value of y: 11111111

The value of f (a function term) and a (an array term), on the other hand, cannot be represented with a simple type. Thus, function values are given as bitwuzla.Kind.LAMBDA, and array values are given as bitwuzla.Kind.ARRAY_STORE. We can retrieve an SMT-LIB2 string representation of the values via bitwuzla.Term.str().

    # f and a, on the other hand, are a function and array term, respectively.
    # The value of these terms is not a value term: for f, it is a lambda term,
    # and the value of a is represented as a store term. Thus we cannot use
    # Term.value(), but we can print the value of the terms via Term.str().
    print('str() representation of value of f:')
    print(bitwuzla.get_value(f))
    print()
    print('str() representation of value of a:')
    print(bitwuzla.get_value(a))

This will print:

str() representation of value of f:
(lambda ((@bzla.var_74 (_ BitVec 8))) (lambda ((@bzla.var_75 (_ BitVec 4))) (ite (and (= @bzla.var_74 #b10011111) (= @bzla.var_75 #b0011)) #b11111111 #b00000000)))

str() representation of value of a:
(store ((as const (Array (_ BitVec 8) (_ BitVec 8))) #b00000000) #b10011111 #b11111111)

Note that the string representation of values representable as simple type (bit-vectors, boolean, floating-point, rounding mode) are given as pure value string (in the given number format) via bitwuzla.Term.value(). Their string representation retrieved via bitwuzla.Term.str(), however, is given in SMT-LIB2 format. For example,

    print(f'str() representation of value of x: {bitwuzla.get_value(x)}')
    print(f'str() representation of value of y: {bitwuzla.get_value(y)}')

This will print:

str() representation of value of x: #b10011111
str() representation of value of y: #b11111111

It is also possible to query the model value of expressions that do not occur in the input formula:

    print(f'value of v = x * x: {v.value(2)}')

This will print:

value of v = x * x: 11000001

Examples

All examples can be found in directory examples.
For instructions on how to build these examples, see examples/README.md.

Quickstart Example

The example used in the Quickstart guide.
The SMT-LIB input for this example can be found at examples/smt2/quickstart.smt2.
The source code for this example can be found at examples/python/quickstart.py.
  1#
  2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
  3#
  4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
  5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
  6#
  7# This file is part of Bitwuzla under the MIT license. See COPYING for more
  8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
  9##
 10
 11from bitwuzla import *
 12
 13if __name__ == "__main__":
 14
 15    # First, create a term manager instance.
 16    tm = TermManager()
 17    # Create a Bitwuzla options instance.
 18    options = Options()
 19    # Then, enable model generation.
 20    options.set(Option.PRODUCE_MODELS, True)
 21    # Now, for illustration purposes, we enable CaDiCaL as SAT solver
 22    # (CaDiCaL is already configured by default).
 23    # Note: This will silently fall back to one of the compiled in SAT solvers
 24    #       if the selected solver is not compiled in.
 25    options.set(Option.SAT_SOLVER, 'cadical')
 26    # Then, create a Bitwuzla instance.
 27    bitwuzla = Bitwuzla(tm, options)
 28
 29    # Create bit-vector sorts of size 4 and 8.
 30    sortbv4 = tm.mk_bv_sort(4)
 31    sortbv8 = tm.mk_bv_sort(8)
 32    # Create function sort.
 33    sortfun = tm.mk_fun_sort([sortbv8, sortbv4], sortbv8)
 34    # Create array sort.
 35    sortarr = tm.mk_array_sort(sortbv8, sortbv8)
 36
 37    # Create two bit-vector constants of that sort.
 38    x = tm.mk_const(sortbv8, "x")
 39    y = tm.mk_const(sortbv8, "y")
 40    # Create fun const.
 41    f = tm.mk_const(sortfun, "f")
 42    # Create array const.
 43    a = tm.mk_const(sortarr, "a")
 44    # Create bit-vector values one and two of the same sort.
 45    one = tm.mk_bv_one(sortbv8)
 46    # Alternatively, you can create bit-vector value one with:
 47    # one = tm.mk_bv_value(sortbv8, "1", 2)
 48    # one = tm.mk_bv_value(sortbv8, 1)
 49    two = tm.mk_bv_value(sortbv8, 2)
 50
 51    # (bvsdiv x (_ bv2 8))
 52    sdiv = tm.mk_term(Kind.BV_SDIV, [x, two])
 53    # (bvashr y (_ bv1 8))
 54    ashr = tm.mk_term(Kind.BV_ASHR, [y, one])
 55    # ((_ extract 3 0) (bvsdiv x (_ bv2 8)))
 56    sdive = tm.mk_term(Kind.BV_EXTRACT, [sdiv], [3, 0])
 57    # ((_ extract 3 0) (bvashr x (_ bv1 8)))
 58    ashre = tm.mk_term(Kind.BV_EXTRACT, [ashr], [3, 0])
 59
 60    # (assert
 61    #     (distinct
 62    #         ((_ extract 3 0) (bvsdiv x (_ bv2 8)))
 63    #         ((_ extract 3 0) (bvashr y (_ bv1 8)))))
 64    bitwuzla.assert_formula(tm.mk_term(Kind.DISTINCT, [sdive, ashre]))
 65    # (assert (= (f x ((_ extract 6 3) x)) y))
 66    bitwuzla.assert_formula(tm.mk_term(
 67        Kind.EQUAL,
 68        [tm.mk_term(Kind.APPLY, [f, x, tm.mk_term(Kind.BV_EXTRACT, [x], [6, 3])]),
 69         y]))
 70    # (assert (= (select a x) y))
 71    bitwuzla.assert_formula(
 72        tm.mk_term(Kind.EQUAL, [tm.mk_term(Kind.ARRAY_SELECT, [a, x]), y]))
 73
 74    # (check-sat)
 75    result = bitwuzla.check_sat()
 76    print('Expect: sat')
 77    print(f'Bitwuzla: {result}')
 78
 79    # Print model in SMT-LIBv2 format.
 80    print('Model:\n(')
 81    for term in [x, y, f, a]:
 82        sort = term.sort()
 83        symbol = term.symbol()
 84        print(f'  (define-fun {symbol if symbol else "@t" + term.id()} (',
 85              end = '')
 86        if sort.is_fun():
 87            value = bitwuzla.get_value(term)
 88            assert value.kind() == Kind.LAMBDA
 89            assert value.num_children() == 2
 90            while value[1].kind() == Kind.LAMBDA:
 91                assert value[0].is_variable()
 92                print(f'({value[0]} {value[0].sort()}) ',
 93                      end = '')
 94                value = value[1]
 95            assert value[0].is_variable()
 96            print(f'({value[0]} {value[0].sort()})) ' \
 97                  + f'{sort.fun_codomain()} {value[1]})')
 98        else:
 99            print(f') {sort} {bitwuzla.get_value(term)})')
100    print(')')
101    print()
102
103    # Print value for x, y, f and a.
104    # Both x and y are bit-vector terms and their value is a bit-vector
105    # value that can be printed via Term.value().
106    print(f'value of x: {bitwuzla.get_value(x).value(2)}')
107    print(f'value of y: {bitwuzla.get_value(y).value(2)}')
108    print()
109    # f and a, on the other hand, are a function and array term, respectively.
110    # The value of these terms is not a value term: for f, it is a lambda term,
111    # and the value of a is represented as a store term. Thus we cannot use
112    # Term.value(), but we can print the value of the terms via Term.str().
113    print('str() representation of value of f:')
114    print(bitwuzla.get_value(f))
115    print()
116    print('str() representation of value of a:')
117    print(bitwuzla.get_value(a))
118    print()
119    # Note that the assignment string of bit-vector terms is given as the
120    # pure assignment string, either in binary, hexadecimal or decimal format,
121    # whereas Term.str() prints the value in SMT-LIB2 format (in the given
122    # bit-vector output number format, binary by default).
123    print(f'str() representation of value of x: {bitwuzla.get_value(x)}')
124    print(f'str() representation of value of y: {bitwuzla.get_value(y)}')
125    print()
126
127    # Query value of bit-vector term that does not occur in the input formula
128    v = bitwuzla.get_value(tm.mk_term(Kind.BV_MUL, [x, x]))
129    print(f'value of v = x * x: {v.value(2)}')

Options Example

An example for how to set and get options.
The SMT-LIB input for this example can be found at examples/smt2/options.smt2.
The source code for this example can be found at examples/python/options.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a Bitwuzla options instance.
16    options = Options()
17
18    # Enable model generation, which expects a boolean configuration value.
19    options.set(Option.PRODUCE_MODELS, True)
20
21    # Increase the verbosity level, which expects an integer value.
22    print(f'Previous verbosity level: {options.get(Option.VERBOSITY)}')
23    options.set(Option.VERBOSITY, 2)
24    print(f'Current verbosity level: {options.get(Option.VERBOSITY)}')
25
26    # Now configure an option that has modes (a choice of configuration values).
27    # First, query which bit-vector solver engine is set.
28    print(f'Default bv solver: {options.get(Option.BV_SOLVER)}')
29    # Then, select the propagation-based local search engine as solver engine.
30    options.set(Option.BV_SOLVER, 'prop')
31    print(f'Current engine: {options.get(Option.BV_SOLVER)}')
32
33    # Now, create a Bitwuzla instance.
34    tm = TermManager()
35    bitwuzla = Bitwuzla(tm, options)
36    # Check sat (nothing to solve, input formula is empty).
37    result = bitwuzla.check_sat()
38    print('Expect: sat')
39    print(f'Bitwuzla: {result}')

Option Info Example

An example for how to get information about options via BitwuzlaOptionInfo.
The source code for this example can be found at examples/python/option_info.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a Bitwuzla options instance.
16    options = Options()
17
18    # Set some options to illustrate current vs default value.
19    options.set(Option.PRODUCE_MODELS, True)
20    options.set(Option.VERBOSITY, 2)
21    options.set(Option.BV_SOLVER, 'prop')
22
23    # Then iterate over all available configuration options and extract info.
24    for opt in Option:
25        info = OptionInfo(options, opt)
26        print(f'  long name:   {info.lng()}')
27        print(f'  short name:  {info.shrt() if info.shrt() else "-"}')
28        print('  kind:        ', end = '')
29        if info.kind() == OptionInfoKind.BOOL:
30            print('bool')
31            print('  values:')
32            print(f'  + current:   {info.cur()}')
33            print(f'  + default:   {info.dflt()}')
34        elif info.kind() == OptionInfoKind.NUMERIC:
35            print('numeric')
36            print('  values:')
37            print(f'  + current:   {info.cur()}')
38            print(f'  + default:   {info.dflt()}')
39            print(f'  + min:       {info.min()}')
40            print(f'  + max:       {info.max()}')
41        else:
42            print('modes')
43            print('  values:')
44            print(f'  + current:   {info.cur()}')
45            print(f'  + default:   {info.dflt()}')
46            print(f'  + modes:     {info.modes()}')
47        print(f'  description: {info.description()}\n')

Incremental Example with push and pop

An incremental example with push and pop.
The SMT-LIB input for this example can be found at examples/smt2/pushpop.smt2.
The source code for this example can be found at examples/python/pushpop.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == "__main__":
14
15    # No options configured, create Bitwuzla instance with default options.
16    tm = TermManager()
17    bitwuzla = Bitwuzla(tm)
18
19    # Create a bit-vector sort of size 1.
20    sortbv1 = tm.mk_bv_sort(1)
21    # Create a bit-vector sort of size 2.
22    sortbv2 = tm.mk_bv_sort(2)
23
24    # Create bit-vector variables.
25    # (declare-const o0 (_ BitVec 1))
26    o0 = tm.mk_const(sortbv1, 'o0')
27    # (declare-const o1 (_ BitVec 1))
28    o1 = tm.mk_const(sortbv1, 'o1')
29    # (declare-const s0 (_ BitVec 2))
30    s0 = tm.mk_const(sortbv2, 's0')
31    # (declare-const s1 (_ BitVec 2))
32    s1 = tm.mk_const(sortbv2, 's1')
33    # (declare-const s2 (_ BitVec 2))
34    s2 = tm.mk_const(sortbv2, 's2')
35    # (declare-const goal (_ BitVec 2))
36    goal = tm.mk_const(sortbv2, 'goal')
37
38    # Create bit-vector values zero, one, three.
39    zero  = tm.mk_bv_zero(sortbv2)
40    one1  = tm.mk_bv_one(sortbv1)
41    one2  = tm.mk_bv_one(sortbv2)
42    three = tm.mk_bv_value(sortbv2, 3)
43
44    # Add some assertions.
45    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [s0, zero]))
46    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [goal, three]))
47
48    # Push, assert, check sat and pop.
49    bitwuzla.push(1)
50    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [s0, goal]))
51    result = bitwuzla.check_sat()
52    print('Expect: unsat')
53    print(f'Bitwuzla: {result}')
54    bitwuzla.pop(1)
55
56    # (assert (= s1 (ite (= o0 (_ sortbv1 1)) (bvadd s0 one) s0)))
57    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL,
58                                    [s1,
59                                     tm.mk_term(Kind.ITE,
60                                             [tm.mk_term(Kind.EQUAL, [o0, one1]),
61                                              tm.mk_term(Kind.BV_ADD, [s0, one2]),
62                                              s0])]))
63
64    # Push, assert, check sat and pop.
65    bitwuzla.push(1)
66    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [s1, goal]))
67    result = bitwuzla.check_sat()
68    print('Expect: unsat')
69    print(f'Bitwuzla: {result}')
70    bitwuzla.pop(1)
71
72    # (assert (= s2 (ite (= o1 (_ sortbv1 1)) (bvadd s1 one) s1)))
73    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL,
74                                    [s2,
75                                     tm.mk_term(Kind.ITE,
76                                             [tm.mk_term(Kind.EQUAL, [o1, one1]),
77                                              tm.mk_term(Kind.BV_ADD, [s1, one2]),
78                                              s1])]))
79
80    # Push, assert, check sat and pop.
81    bitwuzla.push(1)
82    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [s2, goal]))
83    result = bitwuzla.check_sat()
84    print('Expect: unsat')
85    print(f'Bitwuzla: {result}')
86    bitwuzla.pop(1)

Incremental Example with check-sat-assuming

This example shows how to implement the example above with check-sat-assuming.
The SMT-LIB input for this example can be found at examples/smt2/checksatassuming.smt2.
The source code for this example can be found at examples/python/checksatassuming.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https://github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https://github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == "__main__":
14
15    # No options configured, create Bitwuzla instance with default options.
16    tm = TermManager()
17    bitwuzla = Bitwuzla(tm)
18
19    # Create a bit-vector sort of size 1.
20    sortbv1 = tm.mk_bv_sort(1)
21    # Create a bit-vector sort of size 2
22    sortbv2 = tm.mk_bv_sort(2)
23
24    # Create bit-vector variables.
25    # (declare-const o0 (_ BitVec 1))
26    o0 = tm.mk_const(sortbv1, 'o0')
27    # (declare-const o1 (_ BitVec 1))
28    o1 = tm.mk_const(sortbv1, 'o1')
29    # (declare-const s0 (_ BitVec 2))
30    s0 = tm.mk_const(sortbv2, 's0')
31    # (declare-const s1 (_ BitVec 2))
32    s1 = tm.mk_const(sortbv2, 's1')
33    # (declare-const s2 (_ BitVec 2))
34    s2 = tm.mk_const(sortbv2, 's2')
35    # (declare-const goal (_ BitVec 2))
36    goal = tm.mk_const(sortbv2, 'goal')
37
38    # Create bit-vector values zero, one, three.
39    zero  = tm.mk_bv_zero(sortbv2)
40    one1  = tm.mk_bv_one(sortbv1)
41    one2  = tm.mk_bv_one(sortbv2)
42    three = tm.mk_bv_value(sortbv2, 3)
43
44    # Add some assertions.
45    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [s0, zero]))
46    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [goal, three]))
47
48    # (check-sat-assuming ((= s0 goal)))
49    result = bitwuzla.check_sat(tm.mk_term(Kind.EQUAL, [s0, goal]))
50    print('Expect: unsat')
51    print(f'Bitwuzla: {result}')
52
53    # (assert (= s1 (ite (= o0 (_ sortbv1 1)) (bvadd s0 one) s0)))
54    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL,
55                                    [s1,
56                                     tm.mk_term(Kind.ITE,
57                                             [tm.mk_term(Kind.EQUAL, [o0, one1]),
58                                              tm.mk_term(Kind.BV_ADD, [s0, one2]),
59                                              s0])]))
60
61    # (check-sat-assuming ((= s1 goal)))
62    result = bitwuzla.check_sat(tm.mk_term(Kind.EQUAL, [s1, goal]))
63    print('Expect: unsat')
64    print(f'Bitwuzla: {result}')
65
66    # (assert (= s2 (ite (= o1 (_ sortbv1 1)) (bvadd s1 one) s1)))
67    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL,
68                                     [s2,
69                                      tm.mk_term(Kind.ITE,
70                                              [tm.mk_term(Kind.EQUAL, [o1, one1]),
71                                               tm.mk_term(Kind.BV_ADD, [s1, one2]),
72                                               s1])]))
73
74    # (check-sat-assuming ((= s2 goal)))
75    result = bitwuzla.check_sat(tm.mk_term(Kind.EQUAL, [s2, goal]))
76    print('Expect: unsat')
77    print(f'Bitwuzla: {result}')

Unsat Core Example

This example shows how to extract an unsat core. It creates bit-vector and floating-point terms and further illustrates how to create lambda terms (define-fun).

The SMT-LIB input for this example can be found at examples/smt2/unsatcore.smt2.
The source code for this example can be found at examples/python/unsatcore.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a term manager instance.
16    tm = TermManager()
17    # Create a Bitwuzla options instance.
18    options = Options()
19    # Then, enable unsat core extraction.
20    # Note: Unsat core extraction is disabled by default.
21    options.set(Option.PRODUCE_UNSAT_CORES, True)
22
23    # Then, create a Bitwuzla instance.
24    bitwuzla = Bitwuzla(tm, options)
25
26    # Create a bit-vector sort of size 2.
27    sortbv2 = tm.mk_bv_sort(2)
28    # Create a bit-vector sort of size 4.
29    sortbv4 = tm.mk_bv_sort(4)
30    # Create Float16 floatinf-point sort.
31    sortfp16 = tm.mk_fp_sort(5, 11)
32
33    # Create bit-vector variables.
34    # (declare-const x0 (_ BitVec 4))
35    x0 = tm.mk_const(sortbv4, 'x0')
36    # (declare-const x1 (_ BitVec 2))
37    x1 = tm.mk_const(sortbv2, 'x1')
38    # (declare-const x2 (_ BitVec 2))
39    x2 = tm.mk_const(sortbv2, 'x2')
40    # (declare-const x3 (_ BitVec 2))
41    x3 = tm.mk_const(sortbv2, 'x3')
42    # (declare-const x4 Float16)
43    x4 = tm.mk_const(sortfp16, 'x4')
44
45    # Create FP positive zero.
46    fpzero = tm.mk_fp_pos_zero(sortfp16)
47    # Create BV zero of size 4.
48    bvzero = tm.mk_bv_zero(sortbv4)
49
50    # (define-fun f0 ((a Float16)) Bool (fp.gt a (_ +zero 5 11)))
51    a_f0 = tm.mk_var(sortfp16, 'a_f0')
52    f0 = tm.mk_term(Kind.LAMBDA, [a_f0, tm.mk_term(Kind.FP_GT, [a_f0, fpzero])])
53
54    # (define-fun f1 ((a Float16)) (_ BitVec 4) (ite (f0 a) x0 #b0000))
55    a_f1 = tm.mk_var(sortfp16, 'a_f1')
56    f1   = tm.mk_term(
57        Kind.LAMBDA,
58        [a_f1,
59           tm.mk_term(Kind.ITE, [tm.mk_term(Kind.APPLY, [f0, a_f1]), x0, bvzero])])
60
61    # (define-fun f2 ((a Float16)) (_ BitVec 2) ((_ extract 1 0) (f1 a)))
62    a_f2 = tm.mk_var(sortfp16, 'a_f2')
63    f2   = tm.mk_term(
64        Kind.LAMBDA,
65        [a_f2,
66           tm.mk_term(Kind.BV_EXTRACT, [tm.mk_term(Kind.APPLY, [f1, a_f2])], [1, 0])])
67
68    # (assert (! (bvult x2 (f2 (_ +zero 5 11))) :named a0))
69    a0 = tm.mk_term(Kind.BV_ULT, [x2, tm.mk_term(Kind.APPLY, [f2, fpzero])])
70    bitwuzla.assert_formula(a0)
71
72    # (assert (! (= x1 x2 x3) :named a1))
73    a1 = tm.mk_term(Kind.EQUAL, [x1, x2, x3])
74    bitwuzla.assert_formula(a1)
75
76    # (assert (!(= x4 ((_ to_fp_unsigned 5 11) RNE x3)) :named a2))
77    a2 = tm.mk_term(Kind.EQUAL,
78                      [x4,
79                       tm.mk_term(Kind.FP_TO_FP_FROM_UBV,
80                               [tm.mk_rm_value(RoundingMode.RNE), x3],
81                               [5, 11])])
82    bitwuzla.assert_formula(a2)
83
84    # (check-sat)
85    result = bitwuzla.check_sat()
86    print('Expect: unsat')
87    print(f'Bitwuzla: {result}')
88
89    # (get-unsat-core)
90    unsat_core = bitwuzla.get_unsat_core()
91    print('Unsat Core:')
92    print('{')
93    for t in unsat_core:
94        print(f' {t}')
95    print('}')

Unsat Assumptions Example

This example shows how to implement the example above with get-unsat-assumptions.
The SMT-LIB input for this example can be found at examples/smt2/unsatassumptions.smt2.
The source code for this example can be found at examples/python/unsatassumptions.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a term manager instance.
16    tm = TermManager()
17    # Create a Bitwuzla options instance.
18    options = Options()
19    # (set-option :produce-unsat-assumptions true)
20    options.set(Option.PRODUCE_UNSAT_ASSUMPTIONS, True)
21
22    # Then, create a Bitwuzla instance.
23    bitwuzla = Bitwuzla(tm, options)
24
25    # Create Boolean sort.
26    sortbool = tm.mk_bool_sort()
27    # Create a bit-vector sort of size 2.
28    sortbv2 = tm.mk_bv_sort(2)
29    # Create a bit-vector sort of size 4.
30    sortbv4 = tm.mk_bv_sort(4)
31    # Create Float16 floatinf-point sort.
32    sortfp16 = tm.mk_fp_sort(5, 11)
33    # Create bit-vector variables.
34    # (declare-const x0 (_ BitVec 4))
35    x0 = tm.mk_const(sortbv4, 'x0')
36    # (declare-const x1 (_ BitVec 2))
37    x1 = tm.mk_const(sortbv2, 'x1')
38    # (declare-const x2 (_ BitVec 2))
39    x2 = tm.mk_const(sortbv2, 'x2')
40    # (declare-const x3 (_ BitVec 2))
41    x3 = tm.mk_const(sortbv2, 'x3')
42    # (declare-const x4 Float16)
43    x4 = tm.mk_const(sortfp16, 'x4')
44
45    # Create FP positive zero.
46    fpzero = tm.mk_fp_pos_zero(sortfp16)
47    # Create BV zero of size 4.
48    bvzero = tm.mk_bv_zero(sortbv4)
49
50    # (define-fun f0 ((a Float16)) Bool (fp.gt a (_ +zero 5 11)))
51    a_f0 = tm.mk_var(sortfp16, 'a_f0')
52    f0 = tm.mk_term(Kind.LAMBDA, [a_f0, tm.mk_term(Kind.FP_GT, [a_f0, fpzero])])
53
54    # (define-fun f1 ((a Float16)) (_ BitVec 4) (ite (f0 a) x0 #b0000))
55    a_f1 = tm.mk_var(sortfp16, 'a_f1')
56    f1   = tm.mk_term(
57        Kind.LAMBDA,
58        [a_f1,
59           tm.mk_term(Kind.ITE, [tm.mk_term(Kind.APPLY, [f0, a_f1]), x0, bvzero])])
60
61    # (define-fun f2 ((a Float16)) (_ BitVec 2) ((_ extract 1 0) (f1 a)))
62    a_f2 = tm.mk_var(sortfp16, 'a_f2')
63    f2   = tm.mk_term(
64        Kind.LAMBDA,
65        [a_f2,
66           tm.mk_term(Kind.BV_EXTRACT, [tm.mk_term(Kind.APPLY, [f1, a_f2])], [1, 0])])
67
68    # (assert (! (bvult x2 (f2 (_ +zero 5 11))) :named a0))
69    a0 = tm.mk_const(sortbool, 'a0')
70    assumption0 = tm.mk_term(Kind.BV_ULT, [x2, tm.mk_term(Kind.APPLY, [f2, fpzero])])
71    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [a0, assumption0]))
72    # (assert (! (= x1 x2 x3) :named a1))
73    a1          = tm.mk_const(sortbool, 'a1')
74    assumption1 = tm.mk_term(Kind.EQUAL, [x1, x2, x3])
75    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [a1, assumption1]))
76    # (assert (!(= x4 ((_ to_fp_unsigned 5 11) RNE x3)) :named a2))
77    a2          = tm.mk_const(sortbool, 'a2')
78    assumption2 = tm.mk_term(Kind.EQUAL,
79                               [x4,
80                                tm.mk_term(Kind.FP_TO_FP_FROM_UBV,
81                                        [tm.mk_rm_value(RoundingMode.RNE), x3],
82                                        [5, 11])])
83    bitwuzla.assert_formula(tm.mk_term(Kind.EQUAL, [a2, assumption2]))
84
85    # (check-sat-assuming (assumption0 assumption1 assumption2))
86    result = bitwuzla.check_sat(a0, a1, a2)
87    print('Expect: unsat')
88    print(f'Bitwuzla: {result}')
89
90    # (get-unsat-assumptions)
91    unsat_assumptions = bitwuzla.get_unsat_assumptions()
92    print('Unsat Assumptions: {', end = '')
93    for a in unsat_assumptions:
94        print(f' {a}', end = '')
95    print(' }')

Reset Example

This example shows how to reset the solver instance (SMT-LIB command reset).
The SMT-LIB input for this example can be found at examples/smt2/reset.smt2.
The source code for this example can be found at examples/python/reset.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a term manager instance.
16    tm = TermManager()
17    # Create a Bitwuzla options instance.
18    options = Options()
19    # (set-option :produce-models true)
20    options.set(Option.PRODUCE_MODELS, False)
21
22    # Then, create a Bitwuzla instance.
23    bitwuzla = Bitwuzla(tm, options)
24
25    # Create a bit-vector sort of size 3.
26    sortbv3 = tm.mk_bv_sort(3)
27
28    # (declare-const x (_ BitVec 3))
29    x = tm.mk_const(sortbv3, 'x')
30
31    # (assert (= x #b010))
32    bitwuzla.assert_formula(
33        tm.mk_term(Kind.EQUAL, [x, tm.mk_bv_value(sortbv3, 2)]))
34    # (check-sat)
35    result = bitwuzla.check_sat()
36    print('Expect: sat')
37    print(f'Bitwuzla: {result}')
38
39    # (set-option :produce-models true)
40    options.set(Option.PRODUCE_MODELS, True)
41
42    # (reset)
43    # Note: Bitwuzla does not provide an explicit API function for reset since
44    #       this is achieved by simply discarding the current Bitwuzla instance
45    #       and creating a new one.
46    bitwuzla = Bitwuzla(tm, options)
47
48    # (declare-const a ( Array (_ BitVec 2) (_ BitVec 3)))
49    sortbv2 = tm.mk_bv_sort(2)
50    a       = tm.mk_const(tm.mk_array_sort(sortbv2, sortbv3), 'a')
51
52    # (assert (= x #b011))
53    bitwuzla.assert_formula(
54        tm.mk_term(Kind.EQUAL, [x, tm.mk_bv_value(sortbv3, 3)]))
55    # (assert (= x (select a #b01)))
56    bitwuzla.assert_formula(tm.mk_term(
57        Kind.EQUAL,
58        [x, tm.mk_term(Kind.ARRAY_SELECT, [a, tm.mk_bv_value(sortbv2, 1)])]))
59    # (check-sat)
60    result = bitwuzla.check_sat()
61    print('Expect: sat')
62    print(f'Bitwuzla: {result}')
63    # (get-model)
64    print('(')
65    print(f'  (define-fun {x.symbol()} () {x.sort()} {bitwuzla.get_value(x)} )')
66    print(f'  (define-fun {a.symbol()} () {a.sort()} {bitwuzla.get_value(a)} )')
67    print(')')

Reset Assertions Example

This example shows how to reset the currently asserted formulas of a solver instance (SMT-LIB command reset-assertions).
The SMT-LIB input for this example can be found at examples/smt2/reset_assertions.smt2.
The source code for this example can be found at examples/python/reset_assertions.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11from bitwuzla import *
12
13if __name__ == '__main__':
14
15    # First, create a term manager instance.
16    tm = TermManager()
17    # Create a Bitwuzla options instance.
18    options = Options()
19    # (set-option :produce-models true)
20    options.set(Option.PRODUCE_MODELS, True)
21
22    # Then, create a Bitwuzla instance.
23    bitwuzla = Bitwuzla(tm, options)
24
25    # Create a bit-vector sort of size 3.
26    sortbv3 = tm.mk_bv_sort(3)
27
28    # (declare-const x (_ BitVec 3))
29    x = tm.mk_const(sortbv3, 'x')
30
31    # (assert (= x #b010))
32    bitwuzla.assert_formula(
33        tm.mk_term(Kind.EQUAL, [x, tm.mk_bv_value(sortbv3, 2)]))
34    # (check-sat)
35    result = bitwuzla.check_sat()
36    print('Expect: sat')
37    print(f'Bitwuzla: {result}')
38
39    # (assert (= x #b001))
40    bitwuzla.assert_formula(
41        tm.mk_term(Kind.EQUAL, [x, tm.mk_bv_value(sortbv3, 1)]))
42    # (check-sat)
43    result = bitwuzla.check_sat()
44    print('Expect: unsat')
45    print(f'Bitwuzla: {result}')
46
47    # (reset-assertions)
48    # Note: Bitwuzla does not provide an explicit API function for
49    #       reset-assertions since this is achieved by simply discarding
50    #       the current Bitwuzla instance and creating a new one.
51    bitwuzla = Bitwuzla(tm, options)
52
53    # (assert (= x #b011))
54    bitwuzla.assert_formula(
55        tm.mk_term(Kind.EQUAL, [x, tm.mk_bv_value(sortbv3, 3)]))
56    # (check-sat)
57    result = bitwuzla.check_sat()
58    print('Expect: sat')
59    print(f'Bitwuzla: {result}')
60
61    # (get-model)
62    print(f'(\n (define-fun {x.symbol()} () {x.sort()} {bitwuzla.get_value(x)} )\n)')
63

Parsing Example

This example shows how to parse an input file via the API.
The source code for this example can be found at examples/python/parse.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11import sys
12
13from bitwuzla import *
14
15if __name__ == '__main__':
16
17    # First, create a term manager instance.
18    tm = TermManager()
19    # Create a Bitwuzla options instance.
20    options = Options()
21
22    # We will parse example file `smt2/quickstart.smt2`.
23    # Create parser instance.
24    parser = Parser(tm, options)
25
26    # Now parse the input file.
27    print('Expect: sat')
28    print('Bitwuzla: ', end='')
29    sys.stdout.flush()
30    res = parser.parse("../smt2/quickstart.smt2")
31    # We expect no error to occur.
32    assert not res
33
34    # Now we retrieve the set of asserted formulas and print them.
35    assertions = parser.bitwuzla().get_assertions()
36    print('Assertions:')
37    print('{')
38    for a in assertions:
39        print(f' {a}')
40    print('}')
41
42    # Now we add an assertion via parsing from string.
43    parser.parse('(assert (distinct (select a x) y))', True, False)
44    # Now the formula is unsat.
45    print('Expect: unsat')
46    print(f'Bitwuzla: {parser.bitwuzla().check_sat()}')
47
48    # For illustration purposes, we now parse in some declarations and terms 
49    # and sorts from string.
50
51    # Declare bit-vector sort of size 16.
52    bv16 = parser.parse_sort('(_ BitVec 16)')
53    # Create bit-vector sort of size 16 and show that it corresponds to
54    # its string representation '(_ BitVec16)'.
55    assert bv16 == tm.mk_bv_sort(16)
56
57    # Declare Boolean constants 'c' and 'd'.
58    # Note: Declarations are commands (not terms) in the SMT-LIB language.
59    #       Commands must be parsed in via Parser.parse(),
60    #       Parser::parse_term() only supports parsing SMT-LIB terms.
61    parser.parse("(declare-const c Bool)(declare-const d Bool)", True, False)
62    # Declare bit-vector constant 'b'.
63    parser.parse('(declare-const b (_ BitVec 16))', True, False)
64    # Retrieve term representing 'b'.
65    b = parser.parse_term('b')
66    # Retrieve term representing 'c'.
67    c = parser.parse_term('c')
68    # Retrieve term representing 'd'.
69    d = parser.parse_term('d')
70    # Create xor over 'c' and 'd' and show that it corresponds to term
71    # parsed in from its string representation '(xor c d)'.
72    assert parser.parse_term('(xor c d)') == tm.mk_term(Kind.XOR, [c, d])
73    # Create bit-vector addition over 'b' and bit-vector value
74    # '1011111010001010' and show that it corresponds to the term parsed in
75    # from its string representation '(bvadd b #b1011111010001010)'.
76    assert parser.parse_term('(bvadd b #b1011111010001010)') \
77           == tm.mk_term(Kind.BV_ADD,
78                      [b, tm.mk_bv_value(bv16, '1011111010001010', 2)])

Printing Example

This example shows how to print sorts, terms and formulas via the API.
The source code for this example can be found at examples/python/print.py.
  1###
  2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
  3#
  4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
  5# https://github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
  6#
  7# This file is part of Bitwuzla under the MIT license. See COPYING for more
  8# information at https://github.com/bitwuzla/bitwuzla/blob/main/COPYING
  9##
 10
 11from bitwuzla import *
 12
 13if __name__ == "__main__":
 14
 15    # First, create a term manager instance.
 16    tm = TermManager()
 17    # Create a Bitwuzla options instance.
 18    options = Options()
 19    options.set(Option.PRODUCE_MODELS, True)
 20    # Then, create a Bitwuzla instance.
 21    bitwuzla = Bitwuzla(tm, options)
 22    # Create some sorts.
 23    bv8  = tm.mk_bv_sort(8)
 24    bv32 = tm.mk_bv_sort(32)
 25    fp16 = tm.mk_fp_sort(5, 11)
 26    # Create terms.
 27    b     = tm.mk_const(tm.mk_bool_sort(), "b")
 28    bv    = tm.mk_const(bv8, "bv")
 29    fp    = tm.mk_const(fp16, "fp")
 30    rm    = tm.mk_const(tm.mk_rm_sort(), "rm")
 31    fun   = tm.mk_const(tm.mk_fun_sort([bv8, fp16, bv32], fp16), "fun")
 32    zero  = tm.mk_bv_zero(bv8)
 33    ones  = tm.mk_bv_ones(tm.mk_bv_sort(23))
 34    z     = tm.mk_var(bv8, "z")
 35    q     = tm.mk_var(bv8, "q")
 36    lambd = tm.mk_term(Kind.LAMBDA, [z, tm.mk_term(Kind.BV_ADD, [z, bv])])
 37    fpleq = tm.mk_term(
 38        Kind.FP_LEQ,
 39        [tm.mk_term(Kind.APPLY,
 40                  [fun, bv, fp, tm.mk_term(Kind.BV_ZERO_EXTEND, [ones], [9])]),
 41          fp])
 42    exists = tm.mk_term(
 43        Kind.EXISTS,
 44        [q, tm.mk_term(Kind.EQUAL, [zero, tm.mk_term(Kind.BV_MUL, [bv, q])])])
 45    # Assert formulas.
 46    bitwuzla.assert_formula(b)
 47    bitwuzla.assert_formula(
 48        tm.mk_term(Kind.EQUAL, [tm.mk_term(Kind.APPLY, [lambd, bv]), zero]))
 49    bitwuzla.assert_formula(exists)
 50    bitwuzla.assert_formula(fpleq)
 51
 52    # Print sort.
 53    print('Print bit-vector sort of size 32:')
 54    print('---------------------------------')
 55    print(f'str(): {bv32}')
 56    print()
 57
 58    # Print terms.
 59    # Note: Hexadecimal bv output format is ignored if the value is not of size
 60    #       divisible by 4.
 61    print('Print term:')
 62    print('-----------')
 63    print(f'str()      [default]:       {rm}')
 64    print(f'str()      [bin (ignored)]: {rm.str(2)}')
 65    print(f'str()      [dec (ignored)]: {rm.str(10)}')
 66    print(f'str(16)    [hex (ignored)]: {rm.str(16)}')
 67    print()
 68    print(f'str()      [default]: {zero}')
 69    print(f'str()      [bin]:     {zero.str(2)}')
 70    print(f'str(10)    [dec]:     {zero.str(10)}')
 71    print(f'str(16)    [hex]:     {zero.str(16)}')
 72    print()
 73    print(f'str()      [default]:       {fpleq}')
 74    print(f'str()      [bin]:           {fpleq.str()}')
 75    print(f'str(10)    [dec]:           {fpleq.str(10)}')
 76    print(f'str(16)    [hex (ignored)]: {fpleq.str(16)}')
 77    print()
 78
 79    # Print asserted formulas.
 80    # Note: This uses the default bit-vector output format (binary).
 81    expected_smt2 = \
 82            '(set-logic UFBVFP)\n' \
 83            + '(declare-const b Bool)\n' \
 84            + '(declare-const bv (_ BitVec 8))\n' \
 85            + '(declare-const fp (_ FloatingPoint 5 11))\n' \
 86            + '(declare-fun fun ((_ BitVec 8) (_ FloatingPoint 5 11) ' \
 87            + '(_ BitVec 32)) (_ FloatingPoint 5 11))\n' \
 88            + '(assert b)\n' \
 89            + '(assert (= ((lambda ((z (_ BitVec 8))) (bvadd z bv)) bv) ' \
 90            + '#b00000000))\n' \
 91            + '(assert (exists ((q (_ BitVec 8))) (= #b00000000 ' \
 92            + '(bvmul bv q))))\n' \
 93            + '(assert (fp.leq (fun bv fp ((_ zero_extend 9) ' \
 94            + '#b11111111111111111111111)) fp))\n' \
 95            + '(check-sat)\n' \
 96            + '(exit)\n'
 97    res = bitwuzla.print_formula()
 98    assert res == expected_smt2
 99    print('Print formula [default (binary) bv output format]:')
100    print('--------------------------------------------------')
101    print(res)
102
103    # Print asserted formulas using hexadecimal bit-vector output format.
104    expected_smt2 = \
105            '(set-logic UFBVFP)\n' \
106            + '(declare-const b Bool)\n' \
107            + '(declare-const bv (_ BitVec 8))\n' \
108            + '(declare-const fp (_ FloatingPoint 5 11))\n' \
109            + '(declare-fun fun ((_ BitVec 8) (_ FloatingPoint 5 11) ' \
110            + '(_ BitVec 32)) (_ FloatingPoint 5 11))\n' \
111            + '(assert b)\n' \
112            + '(assert (= ((lambda ((z (_ BitVec 8))) (bvadd z bv)) bv) ' \
113            + '#x00))\n' \
114            + '(assert (exists ((q (_ BitVec 8))) (= #x00 (bvmul bv q))))\n' \
115            + '(assert (fp.leq (fun bv fp ((_ zero_extend 9) ' \
116            + '#b11111111111111111111111)) fp))\n' \
117            + '(check-sat)\n' \
118            + '(exit)\n'
119    res = bitwuzla.print_formula("smt2", 16)
120    assert res == expected_smt2
121    print('Print formula [hexadecimal bv output format]:')
122    print('--------------------------------------------------')
123    print(res)
124
125    # Print asserted formulas using decimal bit-vector output format.
126    expected_smt2 = \
127            '(set-logic UFBVFP)\n' \
128            + '(declare-const b Bool)\n' \
129            + '(declare-const bv (_ BitVec 8))\n' \
130            + '(declare-const fp (_ FloatingPoint 5 11))\n' \
131            + '(declare-fun fun ((_ BitVec 8) (_ FloatingPoint 5 11) ' \
132            + '(_ BitVec 32)) (_ FloatingPoint 5 11))\n' \
133            + '(assert b)\n' \
134            + '(assert (= ((lambda ((z (_ BitVec 8))) (bvadd z bv)) bv) ' \
135            + '(_ bv0 8)))\n' \
136            + '(assert (exists ((q (_ BitVec 8))) (= (_ bv0 8) ' \
137            + '(bvmul bv q))))\n' \
138            + '(assert (fp.leq (fun bv fp ((_ zero_extend 9) ' \
139            + '(_ bv8388607 23))) fp))\n' \
140            + '(check-sat)\n' \
141            + '(exit)\n'
142    res = bitwuzla.print_formula("smt2", 10)
143    assert res == expected_smt2
144    print('Print formula [decimal bv output format]:')
145    print('---------------------------------------------')
146    print(res)
147
148    bitwuzla.check_sat()
149
150    # Print values.
151    print('Print value of Boolean predicate:')
152    print('---------------------------------')
153    fpleq_val = bitwuzla.get_value(fpleq).value()
154    print(f'{fpleq}: {fpleq_val} [bool]')
155    print()
156
157    print('Print value of bv const:')
158    print('------------------------')
159    print(f'{bv}: {bitwuzla.get_value(bv).value():>8} [str] (bin)')
160    print(f'{bv}: {bitwuzla.get_value(bv).value(10):>8} [str] (dec)')
161    print(f'{bv}: {bitwuzla.get_value(bv).value(16):>8} [str] (hex)')
162    print()
163
164    print('Print value of RoundingMode const:')
165    print('----------------------------------')
166    print(f'{rm}: {bitwuzla.get_value(rm).value()} [RoundingMode]')
167    print()
168
169    fp_val = bitwuzla.get_value(fp)
170
171    print('Print value of fp const as single bit-vector (base ignored):')
172    print('------------------------------------------------------------')
173    assert fp_val.value(2, False) == fp_val.value(10, False)
174    assert fp_val.value(2, False) == fp_val.value(16, False)
175    print(f'{fp}: {fp_val.value(2, False):>16} [str] (bin)')
176    print(f'{fp}: {fp_val.value(10, False):>16} [str] (dec [ignored])')
177    print(f'{fp}: {fp_val.value(16, False):>16} [str] (hex [ignored])')
178    print()
179
180    print('Print value of fp const as list of component bit-vectors:')
181    print('---------------------------------------------------------')
182    val = fp_val.value(2)
183    print(f'{fp}: [{val[0]}, {val[1]:>5}, {val[2]:>11}] [str] (bin)')
184    val = fp_val.value(10)
185    print(f'{fp}: [{val[0]}, {val[1]:>5}, {val[2]:>11}] [str] (dec)')
186    val = fp_val.value(16)
187    print(f'{fp}: [{val[0]}, {val[1]:>5}, {val[2]:>11}] [str] (hex)')
188    print()

Termination Callback Example

This example shows how to configure a termination callback.
The source code for this example can be found at examples/python/terminator.py.
 1###
 2# Bitwuzla: Satisfiability Modulo Theories (SMT) solver.
 3#
 4# Copyright (C) 2023 by the authors listed in the AUTHORS file at
 5# https:#github.com/bitwuzla/bitwuzla/blob/main/AUTHORS
 6#
 7# This file is part of Bitwuzla under the MIT license. See COPYING for more
 8# information at https:#github.com/bitwuzla/bitwuzla/blob/main/COPYING
 9##
10
11import time
12
13from bitwuzla import *
14
15class TestTerminator:
16    def __init__(self, time_limit):
17        self.start_time = time.time()
18        self.time_limit = time_limit
19
20    def __call__(self):
21        # Terminate after self.time_limit ms passed
22        return (time.time() - self.start_time) * 1000 > self.time_limit
23
24if __name__ == '__main__':
25
26    # First, create a term manager instance.
27    tm = TermManager()
28    # No options configured, create Bitwuzla instance with default options.
29    bitwuzla = Bitwuzla(tm)
30
31    bv = tm.mk_bv_sort(32)
32
33    x = tm.mk_const(bv)
34    s = tm.mk_const(bv)
35    t = tm.mk_const(bv)
36
37    a = tm.mk_term(Kind.DISTINCT,
38                     [tm.mk_term(Kind.BV_MUL, [s, tm.mk_term(Kind.BV_MUL, [x, t])]),
39                      tm.mk_term(Kind.BV_MUL, [tm.mk_term(Kind.BV_MUL, [s, x]), t])])
40
41    # Now, we check that the following formula is unsat.
42    # (assert (distinct (bvmul s (bvmul x t)) (bvmul (bvmul s x) t)))
43    print('> Without terminator (with preprocessing):')
44    print('Expect: unsat')
45    print(f'Bitwuzla: {bitwuzla.check_sat(a)}')
46
47    # Now, for illustration purposes, we disable preprocessing, which will
48    # significantly increase solving time, and connect a terminator instance
49    # that terminates after a certain time limit.
50    options = Options()
51    options.set(Option.PREPROCESS, False)
52    # Create new Bitwuzla instance with reconfigured options.
53    bitwuzla2 = Bitwuzla(tm, options)
54    # Configure and connect terminator.
55    tt = TestTerminator(1)
56    bitwuzla2.configure_terminator(tt)
57
58    # Now, we expect Bitwuzla to be terminated during the check-sat call.
59    print('> With terminator (no preprocessing):')
60    print('Expect: unsat')
61    print(f'Bitwuzla: {bitwuzla2.check_sat(a)}')