diff --git a/spec/changelog.tex b/spec/changelog.tex index 4f0b57acda294ed0d2ee1ea0215735f792fb0845..aeec21900ec53a49aeeccefc07bdbef8e3fb6410 100644 --- a/spec/changelog.tex +++ b/spec/changelog.tex @@ -1,5 +1,13 @@ \subsection*{Unreleased} +Proof rules: +\begin{itemize} + \item Addition of a section describing bitvector proofs. + \item Bitblasting rules: \proofRule{bitblast_extract}, \proofRule{bitblast_add}, + \proofRule{bitblast_ult}. +\end{itemize} + +\noindent Breaking changes: \begin{itemize} \item Allow arbitrary extra annotations in \texttt{assume} commands. diff --git a/spec/doc.tex b/spec/doc.tex index 414fba43a9b9036175dda2df4f5bdbffce2440d3..c354011bc533cb59ce9a758f035f2b337cebf048 100644 --- a/spec/doc.tex +++ b/spec/doc.tex @@ -73,6 +73,7 @@ \newcommand\lsymb[1]{\mathbf{#1}} \DeclareMathOperator*{\subst}{subst} \DeclareMathOperator*{\reify}{reify} +\DeclareMathOperator*{\bvexplode}{bvexplode} \newcommand\groundbox[1]{\boxed{#1}} % Proofs @@ -1688,6 +1689,88 @@ is functional congruence, and \proofRule{sko_forall} works like \end{AletheS} \end{example} +\subsection{Bitvector Reasoning with Bitblasting} + +A standard approach to handle bitvector reasoning in SMT solvers +is bitblasting. Bitblasting\index{bitblasting} works by translating +bitvector\index{bitvector} functions to propositional formulas that +model the logical circuit of the bitvector function. + +To express bitblasting in Alethe proof rules, the the Alethe calculus uses +multiple families of helper functions: $\lsymb{bbT}$, $\lsymb{bitOf}_m$, +$\lsymb{bvsize}$, and $\lsymb{bv}_n^i$. Functions in the families are +distinguished either by overloading ($\lsymb{bbT}$ and $\lsymb{bvsize}$) +or by explicit indexing ($\lsymb{bitOf}_m$ and $\lsymb{bv}_n^i$). +To avoid name clashes with user defined +functions, $\lsymb{bbT}$ is written as \inlineAlethe{@bbT}, $\lsymb{bitOf}$ +as \inlineAlethe{@bitOf}, $\lsymb{bvsize}$ as \inlineAlethe{@bvsize}, and +$\lsymb{bv}$ as \inlineAlethe{@bv}. The SMT-LIB standard specifies +that simple symbols starting with ``\inlineAlethe{@}'' are reserved for +solver generated functions. + +The family $\lsymb{bbT}$ consists of one function for each bitvector sort +$(\lsymb{BitVec}\;n)$. +\[ +\lsymb{bbT}\,:\,\underbrace{\lsymb{Bool}\,\dots\,\lsymb{Bool}}_n\;(\lsymb{BitVec}\;n). +\] + +\noindent +Intuitively, the function $\lsymb{bbT}$ takes a list of boolean arguments and +packs them into a bitvector. +Let $\langle u_1, \dots, u_n\rangle$ denote a bitvector of sort $(\lsymb{BitVec}\;n)$ +where $u_i = \top$ if the bit at position $i$ is $1$, and $u_i = \bot$ otherwise. +The bit $u_n$ is the least significant bit. Then + +\[ +\lsymb{bbT}\; v_1 \dots v_n = \langle v_1, \dots, v_n\rangle . +\] + +\noindent +The $\lsymb{bbT}$ functions could be defined in terms of standard SMT-LIB functions. +\begin{align*} +\lsymb{bbT}\;v_1 \dots v_n :=\; + &\lsymb{concat}\,(\lsymb{concat}\,(\dots \\ + &(\lsymb{concat}\,(\lsymb{ite}\,v_1\,\langle\top\rangle\,\langle\bot\rangle)\,(\lsymb{ite}\,v_2\,\langle\top\rangle\,\langle\bot\rangle))\\ + & \dots \\ + & (\lsymb{ite}\,v_{n-1}\,\langle\top\rangle\,\langle\bot\rangle)) \\ + & (\lsymb{ite}\,v_n\,\langle\top\rangle\,\langle\bot\rangle)) \\ +\end{align*} + +\noindent +The functions $\lsymb{bitOf}_m$ are the inverse of $\lsymb{bbT}$. They extract +a bit of a bitvector as a boolean. Just as the built in $\lsymb{extract}$ +symbol, $\lsymb{bitOf}_m$ is used as an indexed symbol. Hence, for $m \leq n$, we +write \inlineAlethe{(_ @bitOf} $m$ \inlineAlethe{)}, to denote functions +\[ +\lsymb{bitOf}_m : (\lsymb{BitVec}\;n) \to \lsymb{Bool}. +\] +These functions are defined as +\[ +\lsymb{bitOf}_m \langle u_1, \dots, u_n \rangle := u_m. +\] + + +\noindent +The functions $\lsymb{bvsize}$ return the size of a bitvector. Formally, there +is one $\lsymb{bvsize}$ for for each bitvector sort $(\lsymb{BitVec}\;n)$. Each +$\lsymb{bvsize}$ is a constant function that returns $n$. Using notation: + +\begin{align*} +\lsymb{bvsize}& : (\lsymb{BitVec}\;n) \to \mathbb{N}\\ +\lsymb{bvsize}&\;b := n +\end{align*} + +\noindent +Finally, $\lsymb{bv}_n^i$ is a family of constants indexed by two parameters: +a bitvector length $n$, and a natural number $i$. We +write \inlineAlethe{(_ @bv}$n$ $i$ \inlineAlethe{)} for $\lsymb{bv}_n^i$. +The space before $n$ is omitted for historical reasons. +Each $\lsymb{bv}_n^i$ is the bitvector constant that represents the bitvector +of length $n$ that encodes the integer $i$. Formally, it corresponds +to \inlineAlethe{nat2bv[n](i)}, where \inlineAlethe{nat2bv} is defined +as in the SMT-LIB +standard.\footnote{See \url{https://smt-lib.github.io/theories-FixedSizeBitVectors.shtml}.} + \section{The Alethe Rules} \label{apx:rules} \input{rule_list} @@ -1707,3 +1790,8 @@ is functional congruence, and \proofRule{sko_forall} works like \bibliography{publications} \end{document} + +%%% Local Variables: +%%% mode: latex +%%% TeX-master: t +%%% End: diff --git a/spec/rule_list.tex b/spec/rule_list.tex index 0f1b08d09fa8e7b9e21d7722dd39b9566744df29..2152cdadc91a1af19450da1ea5f4d348fc9db219 100644 --- a/spec/rule_list.tex +++ b/spec/rule_list.tex @@ -229,6 +229,16 @@ simplifications.} \ruleref{qnt_simplify} & Simplification of constant quantified formulas. \\ \end{xltabular} +\begin{xltabular}{\linewidth}{l X} +\caption{Bitvector rules.} +\label{rule-tab:simplification}\\ + Rule & Description \\ + \hline +\ruleref{bitblast_extract} & Bitblasting of $\lsymb{extract}$. \\ +\ruleref{bitblast_ult} & Bitblasting of $\lsymb{ult}$. \\ +\ruleref{bitblast_add} & Bitblasting of $\lsymb{add}$. \\ +\end{xltabular} + \subsection{Rule List} \label{sec:alethe:rules-list} @@ -1530,6 +1540,112 @@ constants are unfolded during proof printing. Hence, the slightly strange form and the reordering of equalities. \end{RuleDescription} +\begin{RuleDescription}{bitblast_extract} +\begin{AletheX} +$i$. & \ctxsep & $((\lsymb{extract}\ j\ i)\ x) ≈ (\lsymb{bbT}\ \varphi_i\ \ldots\ \varphi_j)$ & (\currule) \\ +\end{AletheX} + +\noindent +where the formulas $\varphi_k$ are $(\lsymb{bitOf}_k\ x)$ for $i \leq k \leq j$. + +Alternatively, the rule may also be phrased as a ``short-circuiting'' of the +above when $x$ is a $\lsymb{bbT}$ application: + +\medskip +\begin{AletheX} +$i$. & \ctxsep & $((\lsymb{extract}\ j\ i)\ (\lsymb{bbT}\ x_0\ \ldots\ +x_i\ \ldots \ x_j\ \ldots\ x_n)) ≈ (\lsymb{bbT}\ x_i\ \ldots\ x_j)$ & (\currule) \\ +\end{AletheX} + +\noindent +This alternative is based on the validity of the equality +\[ +\lsymb{bitOf}_k\ (\lsymb{bbT}\ x_0\ \ldots\ x_i\ \ldots \ x_j\ \ldots\ x_n) ≈ x_k +\] +for any bit-vector $x$ of size $n+1$, where $0\leq k\leq n$. + +\end{RuleDescription} + +\begin{RuleDescription}{bitblast_ult} +\begin{AletheX} +$i$. & \ctxsep & $(\lsymb{bvult}\ x\ y) ≈ \mathrm{res}_{n-1}$ & (\currule) \\ +\end{AletheX} +in which both $x$ and $y$ must have the same type $(\lsymb{BitVec}\ n)$ and, for +$i\geq 0$ +\[ + \begin{array}{lcl} + \mathrm{res}_0&=&\neg (\lsymb{bitOf}_0\ x) \wedge (\lsymb{bitOf}_0\ y)\\ + \mathrm{res}_{i+1}&=&(((\lsymb{bitOf}_{i+1}\ x) ≈ (\lsymb{bitOf}_{i+1}\ y))\wedge \mathrm{res}_i)\vee + (\neg (\lsymb{bitOf}_{i+1}\ x) \wedge (\lsymb{bitOf}_{i+1}\ y)) + \end{array} +\] + +\noindent +Alternatively, the rule may also be phrased as a ``short-circuiting'' of the +above when $x$ and $y$ are ``$\lsymb{bbT}$'' applications. So given that +\[ + \begin{array}{lcl} + x&=&(\lsymb{bbT}\ x_0\ \ldots\ x_i\ \ldots \ x_j\ \ldots\ x_n)\\ + y&=&(\lsymb{bbT}\ y_0\ \ldots\ y_i\ \ldots \ y_j\ \ldots\ y_n)\\ + \end{array} +\] +then ``$\mathrm{res}$'' can be defined, for $i \geq 0$, as +\[ + \begin{array}{lcl} + \mathrm{res}_0&=&\neg x_0 \wedge y_0\\ + \mathrm{res}_{i+1}&=&((x_{i+1} ≈ y_{i+1})\wedge + \mathrm{res}_i)\vee (\neg x_{i+1}\wedge y_{i+1}) + \end{array} +\] + +\end{RuleDescription} + +\begin{RuleDescription}{bitblast_add} +\begin{AletheX} +$i$. & \ctxsep & $(\lsymb{bvadd}\ x\ y) ≈ A_1$ & (\currule) \\ +\end{AletheX} +in which both $x$ and $y$ must have the same type $(\lsymb{BitVec}\ n)$. +The term ``$A_1$'' is +\begin{align*} +(\lsymb{bbT}\;& (((\lsymb{bitOf}_{0}\ x) \,\lsymb{xor}\,(\lsymb{bitOf}_{0}\ y))\,\lsymb{xor}\,\mathrm{carry}_0) \\ + & (((\lsymb{bitOf}_{1}\ x) \,\lsymb{xor}\,(\lsymb{bitOf}_{1}\ y))\,\lsymb{xor}\,\mathrm{carry}_1) \\ + & \ldots \\ + & (((\lsymb{bitOf}_{n-1}\ x) \,\lsymb{xor}\, (\lsymb{bitOf}_{n-1}\ y))\,\lsymb{xor}\,\mathrm{carry}_{n-1})) +\end{align*} +and for $i\geq 0$ +\[ + \begin{array}{lcl} + \mathrm{carry}_0&=&\bot\\ + \mathrm{carry}_{i+1}&=&((\lsymb{bitOf}_{i}\ x) \wedge (\lsymb{bitOf}_{i}\ y))\vee(((\lsymb{bitOf}_{i}\ x)\,\lsymb{xor}\, (\lsymb{bitOf}_{i}\ y))\wedge \mathrm{carry}_i) + \end{array} +\] + +\noindent +Alternatively, the rule may also be phrased as a ``short-circuiting'' of the +above when $x$ and $y$ are ``$\lsymb{bbT}$'' applications. So given that +\[ + \begin{array}{lcl} + x&=&(\lsymb{bbT}\ x_0\ \ldots\ x_i\ \ldots \ x_j\ \ldots\ x_n)\\ + y&=&(\lsymb{bbT}\ y_0\ \ldots\ y_i\ \ldots \ y_j\ \ldots\ y_n)\\ + \end{array} +\] +then the rule can be alternatively phrased as + +\begin{AletheX} +$i$. & \ctxsep & $(\mathrm{bvadd}\ x\ y) ≈ A_2$ & (\currule) \\ +\end{AletheX} +with $A_2 := (\lsymb{bbT}\ (x_0 \,\lsymb{xor}\, y_0)\,\lsymb{xor}\,\mathrm{carry}_0\ \ldots\ (x_{n-1} + \,\lsymb{xor}\, y_{n-1})\,\lsymb{xor}\,\mathrm{carry}_{n-1})$ and +``$\mathrm{carry}$'' being defined, for $i \geq 0$, as +\[ + \begin{array}{lcl} + \mathrm{carry}_0&=&\bot\\ + \mathrm{carry}_{i+1}&=&(x_i\wedge y_i)\vee((x_i\,\lsymb{xor}\, y_i)\wedge \mathrm{carry}_i) + \end{array} +\] + +\end{RuleDescription} + \clearpage \subsection{Index of Rules} \label{sec:alethe:rules-index}