Theory of Bit-Vectors and Arrays

examples/api/cpp/bitvectors_and_arrays.cpp

 1/******************************************************************************
 2 * This file is part of the cvc5 project.
 3 *
 4 * Copyright (c) 2009-2026 by the authors listed in the file AUTHORS
 5 * in the top-level source directory and their institutional affiliations.
 6 * All rights reserved.  See the file COPYING in the top-level source
 7 * directory for licensing information.
 8 * ****************************************************************************
 9 *
10 * A simple demonstration of the solving capabilities of the cvc5
11 * bit-vector and array solvers.
12 *
13 */
14
15#include <cvc5/cvc5.h>
16
17#include <iostream>
18
19using namespace std;
20using namespace cvc5;
21
22int main()
23{
24  TermManager tm;
25  Solver slv(tm);
26  slv.setOption("produce-models", "true");    // Produce Models
27  slv.setLogic("QF_ABV");                     // Set the logic
28
29  // Consider the following code (where size is some previously defined constant):
30  //
31  //
32  //   Assert (current_array[0] > 0);
33  //   for (unsigned i = 1; i < k; ++i) {
34  //     current_array[i] = 2 * current_array[i - 1];
35  //     Assert (current_array[i-1] < current_array[i]);
36  //     }
37  //
38  // We want to check whether the assertion in the body of the for loop holds
39  // throughout the loop.
40
41  // Setting up the problem parameters
42  uint32_t k = 4;           // number of unrollings (should be a power of 2)
43  uint32_t index_size = 2;  // size of the index, must be log2(k)
44
45  // Sorts
46  Sort elementSort = tm.mkBitVectorSort(32);
47  Sort indexSort = tm.mkBitVectorSort(index_size);
48  Sort arraySort = tm.mkArraySort(indexSort, elementSort);
49
50  // Variables
51  Term current_array = tm.mkConst(arraySort, "current_array");
52
53  // Making a bit-vector constant
54  Term zero = tm.mkBitVector(index_size, 0u);
55
56  // Asserting that current_array[0] > 0
57  Term current_array0 = tm.mkTerm(Kind::SELECT, {current_array, zero});
58  Term current_array0_gt_0 = tm.mkTerm(
59      Kind::BITVECTOR_SGT, {current_array0, tm.mkBitVector(32, 0u)});
60  slv.assertFormula(current_array0_gt_0);
61
62  // Building the assertions in the loop unrolling
63  Term index = tm.mkBitVector(index_size, 0u);
64  Term old_current = tm.mkTerm(Kind::SELECT, {current_array, index});
65  Term two = tm.mkBitVector(32, 2u);
66
67  std::vector<Term> assertions;
68  for (uint32_t i = 1; i < k; ++i)
69  {
70    index = tm.mkBitVector(index_size, i);
71    Term new_current = tm.mkTerm(Kind::BITVECTOR_MULT, {two, old_current});
72    // current[i] = 2 * current[i-1]
73    current_array =
74        tm.mkTerm(Kind::STORE, {current_array, index, new_current});
75    // current[i-1] < current [i]
76    Term current_slt_new_current =
77        tm.mkTerm(Kind::BITVECTOR_SLT, {old_current, new_current});
78    assertions.push_back(current_slt_new_current);
79
80    old_current = tm.mkTerm(Kind::SELECT, {current_array, index});
81  }
82
83  Term query = tm.mkTerm(Kind::NOT, {tm.mkTerm(Kind::AND, assertions)});
84
85  cout << "Asserting " << query << " to cvc5" << endl;
86  slv.assertFormula(query);
87  cout << "Expect sat." << endl;
88  cout << "cvc5: " << slv.checkSat() << endl;
89
90  // Getting the model
91  cout << "The satisfying model is:" << endl;
92  cout << "  current_array = " << slv.getValue(current_array) << endl;
93  cout << "  current_array[0] = " << slv.getValue(current_array0) << endl;
94  return 0;
95}