Abstract
We present the first stable release of our tool Q3B for deciding satisfiability of quantified bitvector formulas. Unlike other stateoftheart solvers for this problem, Q3B is based on translation of a formula to a bdd that represents models of the formula. The tool also employs advanced formula simplifications and approximations by effective bitwidth reduction and by abstraction of bitvector operations. The paper focuses on the architecture and implementation aspects of the tool, and provides a brief experimental comparison with its competitors.
This work has been supported by Czech Science Foundation, grant GA1802177S.
Download conference paper PDF
1 Introduction
Advances in solving formula satisfiability modulo theories (smt) achieved during the last few decades enabled significant progress and practical applications in the area of automated analysis, testing, and verification of various systems. In the case of software and hardware systems, the most relevant theory is the theory of fixedsized bitvectors, as these systems work with inputs expressed as bitvectors (i.e., sequences of bits) and perform bitwise and arithmetic operations on bitvectors. The quantifierfree fragment of this theory is supported by many generalpurpose smt solvers, such as CVC4 [1], MathSAT [7], Yices [10], or Z3 [9] and also by several dedicated solvers, such as Boolector [21] or STP [12]. However, there are some usecases where quantifierfree formulas are not natural or expressive enough. For example, formulas containing quantifiers arise naturally when expressing loop invariants, ranking functions, loop summaries, or when checking equivalence of two symbolically described sets of states [8, 13, 17, 18, 24]. In the following, we focus on smt solvers for quantified bitvector formulas. In particular, this paper describes the stateoftheart smt solver Q3B including its implementation and the inner workings.
Solving of quantified bitvector formulas was first supported by Z3 in 2013 [25] and for a limited set of exists/forall formulas with only a single quantifier alternation by Yices in 2015 [11]. Both of these solvers decide quantified formulas by quantifier instantiation, in which universally quantified variables in the Skolemized formula are repeatedly instantiated by ground terms until the resulting quantifierfree formula is unsatisfiable or a model of the original formula is found. In 2016, we proposed a different approach for solving quantified bitvector formulas: by using binary decision diagrams (bdds) and approximations [14]. For evaluation of this approach, we implemented an experimental smt solver called Q3B, which outperformed both Z3 and Yices. Next solver that was able to solve quantified bitvector formulas was Boolector in 2017, using also an approach based on quantifier instantiation [22]. Unlike Z3, in which the universally quantified variables are instantiated only by constants or subterms of the original formula, Boolector uses a counterexampleguided synthesis approach, in which a suitable ground term for instantiation is synthesized based on the defined grammar. Thanks to this, Boolector was able to outperform Q3B and Z3 on certain classes of formulas. More recently, in 2018, support of quantified bitvector formulas has also been implemented into CVC4 [20]. The approach of CVC4 is also based on quantifier instantiation, but instead of synthesizing terms given by the grammar as Boolector, CVC4 uses predetermined rules based on invertibility conditions, which directly give terms that can prune many spurious models without using potentially expensive counterexampleguided synthesis. The authors of CVC4 have shown that this approach outperforms Z3, CVC4, and the original Q3B. However, Q3B has been substantially improved since the original experimental version. In 2017, we extended it with simplifications of quantified bitvector formulas using unconstrained variables [15]. Further, in 2018, we added the experimental implementation of abstractions of bitvector operations [16]. With these techniques, Q3B is able to decide more formulas than Z3, Boolector, and CVC4. Besides the theoretical improvements, Q3B was also improved in terms of stability, ease of use, technical parts of the implementation, and compliance with the smtlib standard. This tool paper presents the result of these improvements: Q3B 1.0, the first stable version of Q3B.
We briefly summarize the smt solving approach of Q3B. As in most of modern smt solvers, the input formula is first simplified using satisfiabilitypreserving transformations that may reduce the size and complexity of the formula. The simplified formula is then converted to a binary decision diagram (bdd) that represents all assignments satisfying the formula, i.e., the models of the formula. If the bdd represents at least one model, we say that the bdd is satisfiable and it implies satisfiability of the formula. If the bdd represents the empty set of models, we say that it is unsatisfiable and so is the formula. Unfortunately, there are formulas for which the corresponding bdd (or some of the intermediate bdds that appear during its computation) is necessarily exponential in the number of bits in the formula. For example, this is the case for formulas that contain multiplication of two bitvector variables [5]. To be able to deal with such formulas, Q3B computes in parallel also bdds underapproximating and overapproximating the original set of models, i.e., bdds representing subsets and supersets of the original set of models, respectively. The approximating bdds may be much smaller in size than the precise bdd, especially if the approximation is very rough. Still, they can be used to decide satisfiability of the original formula. If an overapproximating bdd is unsatisfiable, the original formula is also unsatisfiable. If the overapproximating bdd is satisfiable, we take one of its models, i.e., an assignment to the toplevel existential variables of the formula, and check whether it is a model of the original formula. If the answer is positive, the original formula is satisfiable. In the other case, we build a more precise overapproximating bdd. Underapproximating bdds are utilized analogously. The only difference is that for unsatisfiable underapproximating bdd, we check the validity of a countermodel, i.e., an assignment to the toplevel universal variables that makes the formula unsatisfiable. The approach is depicted in Fig. 1.
Q3B currently supports two ways of computing the approximating bdds from the input formula. First of these are variable bitwidth approximations in which the effective bitwidth of some variables is reduced. In other words, some of the variables are represented by fewer bits and the rest of the bits is set to zero bits, one bits, or the sign bit of the reduced variable. This approach was originally used by the smt solvers uclid [6] and Boolector [21]. Q3B extends this approach to quantified formulas: if bitwidths of only existentially quantified variables are reduced, the resulting bdd is underapproximating; if bitwidths of only universally quantified variables are reduced, the resulting bdd is overapproximating. The second way to obtain an approximation is bitvector operation abstraction [16], during which the individual bitvector operations may not compute all bits of the result, but produce some donotknow bits if the resulting bdds would exceed a given number of nodes. An underapproximating bdd then represents assignments that satisfy the formula for all possible values of these donotknow bits. Analogously, an overapproximating bdd represents all assignments that satisfy the formula for some value of the donotknow bits. Q3B also supports a combination of these two methods, in which both the effective bitwith of variables is reduced and the limit on the size of bdds is imposed. During an approximation refinement, either the effective bitwidth or the size limit is increased, based on the detected cause of the imprecision.
2 Architecture
This section describes the internal architecture of Q3B. The overall structure including internal and external components and the interactions between them is depicted in Fig. 2. We explain the purpose of the internal components:

SMTLIB Interpreter (implemented in SMTLIBInterpreter.cpp) reads the input file in the smtlib format [3], which is the standard input format for smt solvers. The interpreter executes all the commands from the file. In particular, it maintains the assertion stack and the options set by the user, calls solver when checksat command is issued, and queries Solver if the user requires the model with the command getmodel.

Formula Simplifier (implemented in FormulaSimplifier.cpp) provides interface for all applied formula simplifications, in particular miniscoping, conversion to negation normal form, pure literal elimination, equality propagation, constructive equality resolution (cer) [14], destructive equality resolution (der) [25], simple theoryrelated rewriting, and simplifications using unconstrained variables. Most of these simplifications are implemented directly in this component; only cer, der, and majority of the theoryrelated rewritings are performed by calling Z3 api and simplifications using unconstrained variables are implemented in a separate component of Q3B. The simplifier also converts toplevel existential variables to uninterpreted constants, so their values are also included in a model. Some simplifications that could change models of the formula are disabled if the user enables model generation, i.e., sets :producemodels to true.

Unconstrained Variable Simplifier (implemented in UnconstrainedVariableSimplifier.cpp) provides simplifications of formulas that contain unconstrained variables, i.e., variables that occur only once in the formula. Besides previously published unconstrained variable simplifications [15], which were present in the previous versions of Q3B, this component now also provides new goaldirected simplifications of formulas with unconstrained variables. In these simplifications, we aim to determine whether a subterm containing an unconstrained variable should be minimized, maximized, sign minimized, or sign maximized in order to satisfy the formula. If the subterm should be minimized and contains an unconstrained variable, the term is replaced by a simpler term that gives the minimal result that can be achieved by any value of the unconstrained variable. Similarly for maximization, sign minimization, and sign maximization.

Solver (implemented in Solver.cpp) is the central component of our tool. It calls formula simplifier and then creates three threads for the precise solver, the underapproximating solver, and the overapproximating solver. It also controls the approximation refinement loops of the approximating solvers. Finally, it returns the result of the fastest thread and stores the respective model, if the result was sat.

Formula to BDD Transformer (implemented in the file ExprToBDDTransformer.cpp) performs the actual conversion of a formula to a bdd. Each subterm of the input formula is converted to a vector of bdds (if the subterm’s sort is a bitvector of width n then the constructed vector contains n bdds, each bdd represents one bit of the subterm). Further, each subformula of the input formula is converted to a bdd. These conversions proceed by a straightforward bottomup recursion on the formula syntax tree. The transformer component calls an external library to compute the effect of logical and bitvector operations on bdds and vectors of bdds, respectively. Besides the precise conversion, the transformer can also construct overapproximating and underapproximating bdds. Precision of approximations depends on parameters set by the solver component.

Cache (implemented as a part of ExprToBDDTransformer.cpp) maintains for each converted subformula and subterm the corresponding bdd or a vector of bdds, respectively. Each of the three solvers has its own cache. When an approximating solver increases precision of the approximation, entries of its cache that can be affected by the precision change are invalidated. All the caches are internally implemented by hashtables.
3 Implementation
Q3B is implemented in C++17, is opensource and available under MIT license on GitHub: https://github.com/martinjonas/Q3B. The project development process includes continuous integration and automatic regression tests.
Q3B relies on several external libraries and tools. For representation and manipulation with bdds, Q3B uses the opensource library cudd 3.0 [23]. Since cudd does not support bitvector operations, we use the library by Peter Navrátil [19] that implements bitvector operations on top of cudd. The algorithms in this library are inspired by the ones in the bdd library BuDDy^{Footnote 1} and they provide a decent performance. Nevertheless, we have further improved its performance by several modifications. In particular, we added a specific code for handling expensive operations like bitvector multiplication and division when arguments contain constant bdds. This for example considerably speeds up multiplication whenever one argument contains many constant zero bits, which is a frequent case when we use the variable bitwidth approximation fixing some bits to zero. Further, we have fixed few incorrectly implemented bitvector operations in the original library. Finally, we have extended the library with the support for donotknow bits in inputs of the bitvector operations and we have implemented abstract versions of arithmetic operations that can produce donotknow bits when the result exceeds a given number of bdd nodes.
For parsing the input formulas in smtlib format, Q3B uses antlr parser generated from the grammar^{Footnote 2} for smtlib 2.6 [2]. We have modified the grammar to correctly handle bitvector numerals and to support push and pop commands without numerical argument. The parser allows Q3B to support all bitvector operations and almost all smtlib commands except getassertions, getassignment, getproof, getunsatassumptions, getunsatcore, and all the commands that work with algebraic datatypes. This is in sharp contrast with the previous experimental versions of Q3B, which only collected all the assertions from the input file and performed the satisfiability check regardless of the rest of the commands and of the presence of the checksat command. The reason for this was that the older versions parsed the input file using the Z3 C++ api, which can provide only the list of assertions, not the rest of the smtlib script. Thanks to the new parser, Q3B 1.0 can also provide the user with a model of a satisfiable formula after calling getmodel; this important aspect of other smt solvers was completely missing in the previous versions.
On the other hand, C++ api of the solver Z3 is still used for internal representation of parsed formulas. The Z3 C++ api is also used to perform manipulations with formulas, such as substitution of values for variables, and some of the formula simplifications. Note that these are the only uses of Z3 api in Q3B during solving the formula; no actual smt or satsolving capabilities of Z3 are used during the solving process.
Some classes of Q3B, in particular Solver, FormulaSimplifier, and UnconstrainedVariableSimplifier, expose a public C++ api that can be used by external tools for smt solving or just performing formula simplifications. For example, Solver exposes method Solve(formula, approximationType), which can be used to decide satisfiability by the precise solver, the underapproximating solver, or the overapproximating solver. Solver also exposes the method SolveParallel(formula), which simplifies the input formula and runs all three of these solvers in parallel and returns the first result as depicted in Fig. 1.
4 Experimental Evaluation
We have evaluated the performance of QB3 1.0 and compared it to the latest versions of smt solvers Boolector (v3.0), CVC4 (v1.6), and Z3 (v4.8.4). All tools were used with their default settings except for CVC4, where we used the same settings as in the paper that introduces quantified bitvector solving in CVC4 [20], since they give better results than the default CVC4 settings. As the benchmark set, we have used all 5751 quantified bitvector formulas from the smtlib repository. The benchmarks are divided into 8 distinct families of formulas. We have executed each solver on each benchmark with cpu time limit 20 min and ram limit of 8 GiB. All the experiments were performed in a Ubuntu 16.04 virtual machine within a computer equipped with Intel(R) Core(TM) i78700 CPU @ 3.20 GHz cpu and 32 GiB of ram. For reliable benchmarking we employed BenchExec [4], a tool that allocates specified resources for a program execution and precisely measures their usage. All scripts used for running benchmarks and processing their results, together with detailed descriptions and some additional results not presented in the paper, are available online^{Footnote 3}.
Table 1 shows the numbers of benchmarks in each benchmark family solved by the individual solvers. Q3B is able to solve the most benchmarks in benchmark families 2017Preinerschollsmt08, 2017Preinertptp, 2017PreinerUltimateAutomizer, 2018Preinercav18, and wintersteiger, and it is competitive in the remaining families. In total, Q3B also solves more formulas than each of the other solvers: 116 more than Boolector, 83 more than CVC4, and 139 more than Z3. Although the numbers of solved formulas for the solvers seem fairly similar, the crosscomparison in Table 2 shows that the differences among the individual solvers are actually larger. For each other solver, there are at least 143 benchmarks that can be solved by Q3B but not by the other solver. We think this shows the importance of developing an smt solver based on bdds and approximations besides the solvers based on quantifier instantiation.
5 Conclusions and Future Work
We have described the architecture and inner workings of the first stable version of the stateoftheart smt solver Q3B. Experimental evaluation on all quantified bitvector formulas from smtlib repository shows that this solver slightly outperforms other stateoftheart solvers for such formulas.
As future work, we would like to drop the dependency on the Z3 api: namely to implement our own representation of formulas and reimplement all the simplifications currently outsourced to Z3 api directly in Q3B. We also plan to extend some simplifications with an additional bookkeeping needed to construct a model of the original formula. With these extensions, all simplifications could be used even if the user wants to get a model of the formula. We would also like to implement production of unsatisfiable cores since they are also valuable for software verification.
References
Barrett, C., et al.: CVC4. In: Gopalakrishnan, G., Qadeer, S. (eds.) CAV 2011. LNCS, vol. 6806, pp. 171–177. Springer, Heidelberg (2011). https://doi.org/10.1007/9783642221101_14
Barrett, C., Stump, A., Tinelli, C.: The SMTLIB Standard: Version 2.6. Technical report, Department of Computer Science, The University of Iowa (2017). www.SMTLIB.org
CBarrett, C., Stump, A., Tinelli, C.: The SMTLIB standard: version 2.0. In: Gupta, A., Kroening, D. (eds.) Proceedings of the 8th International Workshop on Satisfiability Modulo Theories, Edinburgh, UK (2010)
Beyer, D., Löwe, S., Wendler, P.: Benchmarking and resource measurement. In: Fischer, B., Geldenhuys, J. (eds.) SPIN 2015. LNCS, vol. 9232, pp. 160–178. Springer, Cham (2015). https://doi.org/10.1007/9783319234045_12
Bryant, R.E.: On the complexity of VLSI implementations and graph representations of boolean functions with application to integer multiplication. IEEE Trans. Comput. 40(2), 205–213 (1991)
Bryant, R.E., Kroening, D., Ouaknine, J., Seshia, S.A., Strichman, O., Brady, B.A.: An abstractionbased decision procedure for bitvector arithmetic. STTT 11(2), 95–104 (2009)
Cimatti, A., Griggio, A., Schaafsma, B.J., Sebastiani, R.: The MathSAT5 SMT solver. In: Piterman, N., Smolka, S.A. (eds.) TACAS 2013. LNCS, vol. 7795, pp. 93–107. Springer, Heidelberg (2013). https://doi.org/10.1007/9783642367427_7
Cook, B., Kroening, D., Rümmer, P., Wintersteiger, C.M.: Ranking function synthesis for bitvector relations. Form. Methods Syst. Des. 43(1), 93–120 (2013)
de Moura, L., Bjørner, N.: Z3: an efficient SMT solver. In: Ramakrishnan, C.R., Rehof, J. (eds.) TACAS 2008. LNCS, vol. 4963, pp. 337–340. Springer, Heidelberg (2008). https://doi.org/10.1007/9783540788003_24
Dutertre, B.: Yices 2.2. In: Biere, A., Bloem, R. (eds.) CAV 2014. LNCS, vol. 8559, pp. 737–744. Springer, Cham (2014). https://doi.org/10.1007/9783319088679_49
Dutertre, B.: Solving exists/forall problems with Yices. In: Workshop on satisfiability Modulo Theories (2015)
Ganesh, V., Dill, D.L.: A decision procedure for bitvectors and arrays. In: Damm, W., Hermanns, H. (eds.) CAV 2007. LNCS, vol. 4590, pp. 519–531. Springer, Heidelberg (2007). https://doi.org/10.1007/9783540733683_52
Gulwani, S., Srivastava, S., Venkatesan, R.: Constraintbased invariant inference over predicate abstraction. In: Jones, N.D., MüllerOlm, M. (eds.) VMCAI 2009. LNCS, vol. 5403, pp. 120–135. Springer, Heidelberg (2008). https://doi.org/10.1007/9783540939009_13
Jonáš, M., Strejček, J.: Solving quantified bitvector formulas using binary decision diagrams. In: Creignou, N., Le Berre, D. (eds.) SAT 2016. LNCS, vol. 9710, pp. 267–283. Springer, Cham (2016). https://doi.org/10.1007/9783319409702_17
Jonáš, M., Strejček, J.: On simplification of formulas with unconstrained variables and quantifiers. In: Gaspers, S., Walsh, T. (eds.) SAT 2017. LNCS, vol. 10491, pp. 364–379. Springer, Cham (2017). https://doi.org/10.1007/9783319662633_23
Jonáš, M., Strejček, J.: Abstraction of bitvector operations for BDDbased SMT solvers. In: Fischer, B., Uustalu, T. (eds.) ICTAC 2018. LNCS, vol. 11187, pp. 273–291. Springer, Cham (2018). https://doi.org/10.1007/9783030025083_15
Kroening, D., Lewis, M., Weissenbacher, G.: Underapproximating loops in C programs for fast counterexample detection. In: Sharygina, N., Veith, H. (eds.) CAV 2013. LNCS, vol. 8044, pp. 381–396. Springer, Heidelberg (2013). https://doi.org/10.1007/9783642397998_26
Mrázek, J., Bauch, P., Lauko, H., Barnat, J.: SymDIVINE: tool for controlexplicit datasymbolic state space exploration. In: Bošnački, D., Wijs, A. (eds.) SPIN 2016. LNCS, vol. 9641, pp. 208–213. Springer, Cham (2016). https://doi.org/10.1007/9783319325828_14
Navrátil, P.: Adding support for bitvectors to BDD libraries CUDD and Sylvan. Bachelor’s thesis, Masaryk University, Faculty of Informatics, Brno (2018)
Niemetz, A., Preiner, M., Reynolds, A., Barrett, C., Tinelli, C.: Solving quantified bitvectors using invertibility conditions. In: Chockler, H., Weissenbacher, G. (eds.) CAV 2018. LNCS, vol. 10982, pp. 236–255. Springer, Cham (2018). https://doi.org/10.1007/9783319961422_16
Niemetz, A., Preiner, M., Wolf, C., Biere, A.: Btor2, BtorMC and Boolector 3.0. In: Chockler, H., Weissenbacher, G. (eds.) CAV 2018. LNCS, vol. 10981, pp. 587–595. Springer, Cham (2018). https://doi.org/10.1007/9783319961453_32
Preiner, M., Niemetz, A., Biere, A.: Counterexampleguided model synthesis. In: Legay, A., Margaria, T. (eds.) TACAS 2017. LNCS, vol. 10205, pp. 264–280. Springer, Heidelberg (2017). https://doi.org/10.1007/9783662545775_15
Somenzi, F.: CUDD: CU Decision Diagram Package Release 3.0.0. University of Colorado at Boulder (2015)
Srivastava, S., Gulwani, S., Foster, J.S.: From program verification to program synthesis. In: Proceedings of the 37th ACM SIGPLANSIGACT Symposium on Principles of Programming Languages, POPL 2010, Madrid, Spain, 17–23 January 2010, pp. 313–326 (2010)
Wintersteiger, C.M., Hamadi, Y., de Moura, L.M.: Efficiently solving quantified bitvector formulas. Form. Methods Syst. Des. 42(1), 3–23 (2013)
Author information
Authors and Affiliations
Corresponding author
Editor information
Editors and Affiliations
Rights and permissions
Open Access This chapter is licensed under the terms of the Creative Commons Attribution 4.0 International License (http://creativecommons.org/licenses/by/4.0/), which permits use, sharing, adaptation, distribution and reproduction in any medium or format, as long as you give appropriate credit to the original author(s) and the source, provide a link to the Creative Commons license and indicate if changes were made.
The images or other third party material in this chapter are included in the chapter's Creative Commons license, unless indicated otherwise in a credit line to the material. If material is not included in the chapter's Creative Commons license and your intended use is not permitted by statutory regulation or exceeds the permitted use, you will need to obtain permission directly from the copyright holder.
Copyright information
© 2019 The Author(s)
About this paper
Cite this paper
Jonáš, M., Strejček, J. (2019). Q3B: An Efficient BDDbased SMT Solver for Quantified BitVectors. In: Dillig, I., Tasiran, S. (eds) Computer Aided Verification. CAV 2019. Lecture Notes in Computer Science(), vol 11562. Springer, Cham. https://doi.org/10.1007/9783030255435_4
Download citation
DOI: https://doi.org/10.1007/9783030255435_4
Published:
Publisher Name: Springer, Cham
Print ISBN: 9783030255428
Online ISBN: 9783030255435
eBook Packages: Computer ScienceComputer Science (R0)