Skip to content

Commit c566035

Browse files
committed
feat: lookahead for SearchM
1 parent 41458a0 commit c566035

File tree

4 files changed

+85
-16
lines changed

4 files changed

+85
-16
lines changed

src/Lean/Meta/Tactic/Grind/Intro.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,16 @@ def intros (generation : Nat) : SearchM Unit := do
247247
unless (← applyCases? fvarId generation) do
248248
addHypothesis fvarId generation
249249

250+
/--
251+
Similar to `intros`, but returns `true` if new hypotheses have been added,
252+
and `false` otherwise.
253+
-/
254+
def intros' (generation : Nat) : SearchM Bool := do
255+
let target ← (← getGoal).mvarId.getType
256+
if target.isFalse then return false
257+
intros generation
258+
return true
259+
250260
/-- Asserts a new fact `prop` with proof `proof` to the given `goal`. -/
251261
def assertAt (proof : Expr) (prop : Expr) (generation : Nat) : SearchM Unit := do
252262
if isEagerCasesCandidate (← getGoal) prop then

src/Lean/Meta/Tactic/Grind/Lookahead.lean

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,79 @@ import Lean.Meta.Tactic.Grind.Intro
99
import Lean.Meta.Tactic.Grind.Arith
1010
import Lean.Meta.Tactic.Grind.Split
1111
import Lean.Meta.Tactic.Grind.EMatch
12+
import Lean.Meta.Tactic.Grind.SearchM
1213

1314
namespace Lean.Meta.Grind
1415

15-
private partial def solve (generation : Nat) (goal : Goal) : GrindM Bool := do
16+
private partial def solve (generation : Nat) : SearchM Bool := withIncRecDepth do
17+
unless (← get).choiceStack.isEmpty do
18+
return false -- `splitNext` should have been configured to not create choice points
19+
if (← getGoal).inconsistent then
20+
return true
21+
if (← intros' generation <||> assertAll <||> Arith.check <||> splitNext <||> ematch) then
22+
solve generation
23+
else
24+
return false
25+
26+
private def tryLookahead (e : Expr) : GoalM Bool :=
27+
withTheReader Grind.Context
28+
(fun ctx => { ctx with config.qlia := true, cheapCases := true }) do
29+
-- TODO: if `e` is an arithmetic expression, we can avoid creating an auxiliary goal.
30+
-- We can assert it directly to the arithmetic module.
31+
-- Remark: We can simplify this code because the lookahead only really worked for arithmetic.
32+
trace_goal[grind.lookahead.try] "{e}"
33+
let goal ← get
34+
let proof? ← withoutModifyingMCtx do
35+
let tag ← goal.mvarId.getTag
36+
let target ← mkArrow (mkNot e) (← getFalseExpr)
37+
let mvar ← mkFreshExprSyntheticOpaqueMVar target tag
38+
let goalAux := { goal with mvarId := mvar.mvarId!, newFacts := {} }
39+
let gen ← getGeneration e
40+
let (ok, _) ← (solve gen).run goalAux
41+
if ok then
42+
return some (← instantiateMVars mvar)
43+
else
44+
return none
45+
if let some proof := proof? then
46+
trace[grind.lookahead.assert] "{e}"
47+
pushEqTrue e <| mkApp2 (mkConst ``Grind.of_lookahead) e proof
48+
processNewFacts
49+
return true
50+
else
51+
return false
52+
53+
def lookahead : GoalM Bool := do
54+
unless (← getConfig).lookahead do
55+
return false
56+
if (← get).split.lookaheads.isEmpty then
57+
return false
58+
let mut postponed := []
59+
let mut progress := false
60+
let infos := (← get).split.lookaheads
61+
modify fun s => { s with split.lookaheads := [] }
62+
for info in infos do
63+
if (← isInconsistent) then
64+
return true
65+
match (← checkSplitStatus info) with
66+
| .resolved => progress := true
67+
| .ready _ _ true
68+
| .notReady => postponed := info :: postponed
69+
| .ready _ _ false =>
70+
if (← tryLookahead info.getExpr) then
71+
progress := true
72+
else
73+
postponed := info :: postponed
74+
if progress then
75+
modify fun s => { s with
76+
split.lookaheads := s.split.lookaheads ++ postponed.reverse
77+
}
78+
return true
79+
else
80+
return false
81+
82+
/-! TODO: delete rest of the file. -/
83+
84+
private partial def solveOld (generation : Nat) (goal : Goal) : GrindM Bool := do
1685
cont (← introsOld generation goal)
1786
where
1887
cont (goals : List Goal) : GrindM Bool := do
@@ -35,7 +104,7 @@ where
35104
else
36105
return false
37106

38-
private def tryLookahead (e : Expr) : GoalM Bool := do
107+
private def tryLookaheadOld (e : Expr) : GoalM Bool := do
39108
-- TODO: if `e` is an arithmetic expression, we can avoid creating an auxiliary goal.
40109
-- We can assert it directly to the arithmetic module.
41110
-- Remark: We can simplify this code because the lookahead only really worked for arithmetic.
@@ -46,7 +115,7 @@ private def tryLookahead (e : Expr) : GoalM Bool := do
46115
let target ← mkArrow (mkNot e) (← getFalseExpr)
47116
let mvar ← mkFreshExprMVar target .syntheticOpaque tag
48117
let gen ← getGeneration e
49-
if (← solve gen { goal with mvarId := mvar.mvarId! }) then
118+
if (← solveOld gen { goal with mvarId := mvar.mvarId! }) then
50119
return some (← instantiateMVars mvar)
51120
else
52121
return none
@@ -63,7 +132,7 @@ private def withLookaheadConfig (x : GrindM α) : GrindM α := do
63132
(fun ctx => { ctx with config.qlia := true, cheapCases := true })
64133
x
65134

66-
def lookahead : GrindTactic := fun goal => do
135+
def lookaheadOld : GrindTactic := fun goal => do
67136
unless (← getConfig).lookahead do
68137
return none
69138
if goal.split.lookaheads.isEmpty then
@@ -82,7 +151,7 @@ def lookahead : GrindTactic := fun goal => do
82151
| .ready _ _ true
83152
| .notReady => postponed := info :: postponed
84153
| .ready _ _ false =>
85-
if (← tryLookahead info.getExpr) then
154+
if (← tryLookaheadOld info.getExpr) then
86155
progress := true
87156
else
88157
postponed := info :: postponed

src/Lean/Meta/Tactic/Grind/SearchM.lean

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,4 @@ def nextGoal? : SearchM (Option Nat) := do
219219
return some choice.generation
220220
unreachable!
221221

222-
/--
223-
Execute `x` using the current goal as the starting goal.
224-
The state is not updated.
225-
-/
226-
def searchUsing (x : SearchM α) : GoalM α := do
227-
let goal ← get
228-
let goal := { goal with newFacts := {} }
229-
let (a, _) ← x.run goal
230-
return a
231-
232222
end Lean.Meta.Grind

src/Lean/Meta/Tactic/Grind/Solve.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def tryEmatch : Goal → M Bool := applyTac ematchOld
5858

5959
def tryArith : Goal → M Bool := applyTac Arith.checkOld
6060

61-
def tryLookahead : Goal → M Bool := applyTac lookahead
61+
def tryLookahead : Goal → M Bool := applyTac lookaheadOld
6262

6363
def tryMBTC : Goal → M Bool := applyTac Arith.Cutsat.mbtcTac
6464

0 commit comments

Comments
 (0)