-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
184 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import Lean.Elab.Tactic.BVDecide.Frontend.BVDecide | ||
|
||
open Lean | ||
|
||
private partial def getIntrosSize (e : Expr) : Nat := | ||
go 0 e | ||
where | ||
go (size : Nat) : Expr → Nat | ||
| .forallE _ _ b _ => go (size + 1) b | ||
| .mdata _ b => go size b | ||
| _ => size | ||
|
||
/-- | ||
Introduce only forall binders and preserve names. | ||
-/ | ||
def _root_.Lean.MVarId.introsP (mvarId : MVarId) : MetaM (Array FVarId × MVarId) := do | ||
let type ← mvarId.getType | ||
let type ← instantiateMVars type | ||
let n := getIntrosSize type | ||
if n == 0 then | ||
return (#[], mvarId) | ||
else | ||
mvarId.introNP n | ||
|
||
structure Context where | ||
acNf : Bool | ||
parseOnly : Bool | ||
timeout : Nat | ||
input : String | ||
maxSteps : Nat | ||
disableAndFlatten : Bool | ||
disableEmbeddedConstraintSubst : Bool | ||
disableKernel : Bool | ||
|
||
abbrev SolverM := ReaderT Context MetaM | ||
|
||
namespace SolverM | ||
|
||
def getParseOnly : SolverM Bool := return (← read).parseOnly | ||
def getInput : SolverM String := return (← read).input | ||
def getKernelDisabled : SolverM Bool := return (← read).disableKernel | ||
|
||
def getBVDecideConfig : SolverM Elab.Tactic.BVDecide.Frontend.BVDecideConfig := do | ||
let ctx ← read | ||
return { | ||
timeout := ctx.timeout | ||
acNf := ctx.acNf | ||
embeddedConstraintSubst := !ctx.disableEmbeddedConstraintSubst | ||
andFlattening := !ctx.disableAndFlatten | ||
maxSteps := ctx.maxSteps | ||
structures := false, | ||
} | ||
|
||
def run (x : SolverM α) (ctx : Context) (coreContext : Core.Context) (coreState : Core.State) : | ||
IO α := do | ||
let (res, _, _) ← ReaderT.run x ctx |> (Meta.MetaM.toIO · coreContext coreState) | ||
return res | ||
|
||
end SolverM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import Leanwuzla.Basic | ||
|
||
open Lean Std.Sat Std.Tactic.BVDecide | ||
open Elab.Tactic.BVDecide | ||
open Elab.Tactic.BVDecide.Frontend | ||
|
||
def runSolver (cnf : CNF Nat) (solver : System.FilePath) (lratPath : System.FilePath) | ||
(trimProofs : Bool) (timeout : Nat) (binaryProofs : Bool) : | ||
CoreM (Except (Array (Bool × Nat)) (Array LRAT.IntAction)) := do | ||
IO.FS.withTempFile fun cnfHandle cnfPath => do | ||
withTraceNode `sat (fun _ => return "Serializing SAT problem to DIMACS file") do | ||
-- lazyPure to prevent compiler lifting | ||
cnfHandle.putStr (← IO.lazyPure (fun _ => cnf.dimacs)) | ||
cnfHandle.flush | ||
|
||
let res ← | ||
withTraceNode `sat (fun _ => return "Running SAT solver") do | ||
External.satQuery solver cnfPath lratPath timeout binaryProofs | ||
if let .sat assignment := res then | ||
return .error assignment | ||
|
||
let lratProof ← | ||
withTraceNode `sat (fun _ => return "Obtaining LRAT certificate") do | ||
LratCert.load lratPath trimProofs | ||
|
||
return .ok lratProof | ||
|
||
def decideSmtNoKernel (type : Expr) : SolverM UInt32 := do | ||
let solver ← TacticContext.new.determineSolver | ||
let g := (← Meta.mkFreshExprMVar type).mvarId! | ||
let (_, g) ← g.introsP | ||
trace[Meta.Tactic.bv] m!"Working on goal: {g}" | ||
try | ||
g.withContext $ IO.FS.withTempFile fun _ lratPath => do | ||
let cfg ← SolverM.getBVDecideConfig | ||
match ← Normalize.bvNormalize g cfg with | ||
| some g => | ||
let bvExpr := (← M.run <| reflectBV g).bvExpr | ||
|
||
let entry ← | ||
withTraceNode `bv (fun _ => return "Bitblasting BVLogicalExpr to AIG") do | ||
-- lazyPure to prevent compiler lifting | ||
IO.lazyPure (fun _ => bvExpr.bitblast) | ||
let aigSize := entry.aig.decls.size | ||
trace[Meta.Tactic.bv] s!"AIG has {aigSize} nodes." | ||
|
||
let (cnf, map) ← | ||
withTraceNode `sat (fun _ => return "Converting AIG to CNF") do | ||
-- lazyPure to prevent compiler lifting | ||
IO.lazyPure (fun _ => | ||
let (entry, map) := entry.relabelNat' | ||
let cnf := Std.Sat.AIG.toCNF entry | ||
(cnf, map) | ||
) | ||
|
||
let res ← | ||
withTraceNode `sat (fun _ => return "Obtaining external proof certificate") do | ||
runSolver cnf solver lratPath cfg.trimProofs cfg.timeout cfg.binaryProofs | ||
|
||
match res with | ||
| .ok cert => | ||
let certFine ← | ||
withTraceNode `sat (fun _ => return "Verifying LRAT certificate") do | ||
-- lazyPure to prevent compiler lifting | ||
IO.lazyPure (fun _ => LRAT.check cert cnf) | ||
if certFine then | ||
logInfo "unsat" | ||
return (0 : UInt32) | ||
else | ||
logInfo "Error: Failed to check LRAT cert" | ||
return (1 : UInt32) | ||
| .error assignment => | ||
logInfo "sat" | ||
return (0 : UInt32) | ||
| none => | ||
logInfo "unsat" | ||
return (0 : UInt32) | ||
catch e => | ||
-- TODO: improve handling of sat cases. This is a temporary workaround. | ||
let message ← e.toMessageData.toString | ||
if message.startsWith "None of the hypotheses are in the supported BitVec fragment" then | ||
-- We fully support SMT-LIB v2.6. Getting the above error message means | ||
-- the goal was reduced to `False` with only `True` as an assumption. | ||
logInfo "sat" | ||
return (0 : UInt32) | ||
else | ||
logError m!"Error: {e.toMessageData}" | ||
return (1 : UInt32) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
leanprover/lean4:nightly-2025-01-01 | ||
leanprover/lean4-pr-releases:pr-release-6856 |