-
Notifications
You must be signed in to change notification settings - Fork 453
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Strict Ackermannization (bv_ac_eager) tactic for QF_UFBV #5657
base: master
Are you sure you want to change the base?
Conversation
Mathlib CI status (docs):
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a partial pass, so far I'm missing some documentation to explain what's what, have not attempted to grok the correctness of the code yet
b59b96f
to
cc0e4df
Compare
ffc62dc
to
1a6ae3c
Compare
Co-authored-by: Alex Keizer <[email protected]>
changelog-library |
awaiting-review |
CC @hargoniX :) |
awaiting-author |
awaiting-review |
| .bool => m!"bool" | ||
| .bitVec w => m!"BitVec {w}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .bool => m!"bool" | |
| .bitVec w => m!"BitVec {w}" | |
| .bool => m!"bool" | |
| .bitVec w => m!"bitVec {w}" |
Consistently capitalize these, please!
/-- | ||
NOTE: is it sensible to hash an array of arguments? | ||
We may want to use something like a trie to index these. | ||
Consider swiching to something like `Trie`. | ||
-/ | ||
abbrev ArgumentArray := Array Argument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might want to give this an actual descriptive docstring, and move the NOTE to a non-doc comment.
/-- Types that can be bitblasted by bv_decide. -/ | ||
inductive BVTy | ||
/-- Booleans. -/ | ||
| bool | ||
/-- Bitvectors of a fixed width `w`. -/ | ||
| bitVec (w : Nat) | ||
deriving Hashable, DecidableEq, Inhabited |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check your whitespace, I think this is indented one level too much
end CallInfo | ||
structure State where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
end CallInfo | |
structure State where | |
end CallInfo | |
structure State where |
/-- A counter for generating fresh names. -/ | ||
gensymCounter : Nat := 0 | ||
|
||
def State.init : State where |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def State.init : State where | |
def State.init : State := {} |
The where
without anything after reads a bit weird to me, I'd prefer something more explicit, but this is pure aesthethics/taste, so feel free to ignore
/-- This is how we build the congruence lemma for `n` arguments. -/ | ||
private example (f : X1 → X2 → O) | ||
-- we have these already. | ||
(x1 x1' : X1) (x2 x2' : X2) | ||
(ackEqApp : fx1x2 = f x1 x2) | ||
(ackEqApp' : fx1'x2' = f x1' x2') | ||
-- to be intros'd | ||
(h1 : x1 = x1') | ||
(h2 : x2 = x2') : | ||
fx1x2 = fx1'x2' := | ||
let appEqApp : f x1 x2 = f x1' x2' := congr (congr (Eq.refl f) h1) h2 | ||
Eq.trans (Eq.trans ackEqApp appEqApp) (Eq.symm ackEqApp') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like they were notes for the implementation, but do we want to keep them around?
|
||
initialize Lean.registerTraceClass `Meta.Tactic.bv_ack | ||
|
||
namespace Ack |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me, "ack" means acknowledge. In the context of this file, the abbrevation makes sense, but for the namespace we might want to spell out Ackermannize fully
Intuitively, this is the only fact that they theory UF can propagate, | ||
and we thus encode it directly as a SAT formula, | ||
by abstracting out the actual function application into a new free variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Intuitively, this is the only fact that they theory UF can propagate, | |
and we thus encode it directly as a SAT formula, | |
by abstracting out the actual function application into a new free variable. | |
Intuitively, this is the only fact that the theory UF can propagate, | |
and we thus encode it directly as a SAT formula, | |
by abstracting out the actual function application into a new free variable. |
import Std.Tactic.BVAckermannize.Syntax | ||
|
||
/-! | ||
This directory contains the lazy ackermannization tactic. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This directory contains the lazy ackermannization tactic. | |
This directory contains the eager ackermannization tactic. |
|
||
/-! | ||
This directory contains the lazy ackermannization tactic. | ||
This uses lean's builtin bitblaster to reduce uninterpreted functions + bitvectors to SAT. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it actually integrate bv_decide
into the tactic? I thought it rather reduces uninterpreted functions + bitvectors
to bitvectors
(which bv_decide can then solve by reduction to SAT)
This PR implements strict Ackermannization, which is an algorithmic technique to reduce
QF_UFBV
intoQF_BV
.The implementation walks over the goals and the hypotheses. When it encounters a function application
(f x1 x2 ... xn)
where the type signature off
isBitVec k1 -> BitVec k2 -> ... -> BitVec kn -> BitVec ko
, it creates a new variablefAppX : BitVec k0
, and an equationfAppX = f x1 ... xn
. Next, when it encounters another application of the same function(f y1 y2 ... yn)
, it creates a new variablefAppY : BitVec k0
, and another equationfAppY = f y1 ... yn
.After the walk, we loop over all pairs of applications of the function
f
we have abstracted. In this case, we havefAppX
andfAppY
. For these, we build an extensionality equation, which says that ifIntuitively, this is the only fact that the theory UF can propagate, and we thus encode it directly as a SAT formula,
by abstracting out the actual function application into a new free variable.
This implementation creates the Ackermann variables (
fAppX, fAppY
) first and then, in a subsequent phase, adds all the Ackermann equations (hAppXAppYExt
). This anticipates the next patches, which will implement incremental Ackermannization, where we will use the counterexample from the model to selectively add Ackerman equations.