\myheading{Can rand() generate 100 consecutive zeroes? (SMT-LIB versions)} \leveldown{} Let's implement this in terms of SMT-LIB language. \myheading{Version 1: unrolled} \lstinputlisting[style=customsmt]{\CURPATH/1_unrolled.smt} \TT{QF\_BV} logic means "quantifier free, bitvector". So far so good, but a bit redundant. Can we wrap these redundant parts into function(s)? \myheading{Version 2: functions} We can define functions in SMT-LIB language: \lstinputlisting[style=customsmt]{\CURPATH/2_func.smt} \myheading{Version 3: function + array} Now arrays. You see, declaring many "state" variables is also redundant. Can't we use arrays here? \lstinputlisting[style=customsmt]{\CURPATH/3_array_func.smt} Here we use the \TT{QF\_ABV} SMT logic: same as in \TT{QF\_BV}, but \TT{A} means \textit{arrays}. We use arrays also in this example: \ref{SMT_popcount}. Here we define relationships between various elements of array: \begin{lstlisting} (assert (= (PRNG_step (select states #x1)) (select states #x2))) (assert (= (PRNG_step (select states #x2)) (select states #x3))) (assert (= (PRNG_step (select states #x3)) (select states #x4))) \end{lstlisting} Here we \textit{read} from array: \begin{lstlisting} (assert (= (PRNG_get_result_modulo_1000 (select states #x2)) (_ bv0 32))) (assert (= (PRNG_get_result_modulo_1000 (select states #x3)) (_ bv0 32))) (assert (= (PRNG_get_result_modulo_1000 (select states #x4)) (_ bv0 32))) \end{lstlisting} \myheading{Version 4: \ac{UF} + array} We can also define function using \ac{UF}. These functions that has no body. This is a bit unusual concept for a programmer accustomed to languages derived from Algol or Lisp. However, you can describe behaviour of \ac{UF} using additional constraints. \lstinputlisting[style=customsmt]{\CURPATH/4_array_UF.smt} Take a closer look: \begin{lstlisting}[style=customsmt] (assert (forall ((x (_ BitVec 32))) (= (rand x) (bvadd (bvmul x const1) const2)))) \end{lstlisting} In Plain English, this means: "for all (32-bit) X's, rand(x)'s value is always equals to (bvadd (bvmul X const1) const2))))". This is First-Order Logic. "For all" is an \textit{universal quantifier}, usually denoted as an "A" letter upside down: $\forall$. Since quantifiers exists in the example, another SMT logic is to be used: \TT{AUFBV} (A stands for Arrays, UF for \ac{UF}, BV stands for bitvector, but notice we dropped the \TT{QF\_} prefix). UF's are then \textit{called}, as in Lisp language: "(function\_name arg1 arg2 ...)". \myheading{Performance} (Time in seconds, running on my relic Intel Core 2 Duo T9400, clocked at 2.13GHz.) \iffalse | SMT-solver | v1 (unrolled) | v2 (functions) | v3 (function + array) | v4 (UF + array) | |---------------------+---------------+----------------+-----------------------+-----------------| | STP 2.3.3 | 3.6 | 3.6 | 5.6 | * | | Boolector 3.2.1 | 8 | 8 | 5 | 3.5 | | CVC4 1.9-prerelease | 21 | 21 | 16 | 5 | | Z3 4.8.9 | 23 | 23 | 26 | 133 | | Yices 2.6.2 | 6 | 6 | 11 | * | | MK85 | 209 | | | | \fi \begin{center} \begin{tabular}{ | l | l | l | l | l | } \hline SMT-solver & v1 (unrolled) & v2 (functions) & v3 (function + array) & v4 (UF + array) \\ \hline STP 2.3.3 & 3.6 & 3.6 & 5.6 & * \\ Boolector 3.2.1 & 8 & 8 & 5 & 3.5 \\ CVC4 1.9-prerelease & 21 & 21 & 16 & 5 \\ Z3 4.8.9 & 23 & 23 & 26 & 133 \\ Yices 2.6.2 & 6 & 6 & 11 & * \\ MK85 & 209 & * & * & * \\ \hline \end{tabular} \end{center} *) Couldn't manage to run it Also, since the first version of the example is that simple, my toy-level bitblaster (MK85, that is based on picosat SAT solver) can solve it, slower by factor of 10x then others, but still... \myheading{Bruteforce} But what about bruteforce? Yes, you can solve this problem using simple bruteforce. 32-bit search space is small enough. But... this is what I can do in pure C: \lstinputlisting[style=customc]{\CURPATH/BF.c} If compiled with \TT{GCC -O3}, it will run for 12 seconds on the same CPU. Faster than Z3 and CVC4, but slower than STP and Boolector! Modulo division is a heavy operation, but it seems, these SMT solvers can find ways to cut the search space! \myheading{The files} \url{\RepoURL/\CURPATH} \levelup{}