lean4-htt/src/Lean/Meta/Tactic/Grind/Solve.lean
Leonardo de Moura 746e3a9f42
feat: model search skeleton for cutsat (#7155)
This PR implements some infrastructure for the model search procedure in
cutsat.
2025-02-20 03:41:39 +00:00

98 lines
2.7 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Lean.Meta.Tactic.Grind.Combinators
import Lean.Meta.Tactic.Grind.Split
import Lean.Meta.Tactic.Grind.EMatch
import Lean.Meta.Tactic.Grind.Arith
namespace Lean.Meta.Grind
namespace Solve
structure State where
todo : List Goal
failures : List Goal := []
stop : Bool := false
private abbrev M := StateRefT State GrindM
def getNext? : M (Option Goal) := do
let goal::todo := (← get).todo | return none
modify fun s => { s with todo }
return some goal
def pushGoal (goal : Goal) : M Unit :=
modify fun s => { s with todo := goal :: s.todo }
def pushGoals (goals : List Goal) : M Unit :=
modify fun s => { s with todo := goals ++ s.todo }
def pushFailure (goal : Goal) : M Unit := do
modify fun s => { s with failures := goal :: s.failures }
if (← get).failures.length ≥ (← getConfig).failures then
modify fun s => { s with stop := true }
@[inline] def stepGuard (x : Goal → M Bool) (goal : Goal) : M Bool := do
try
x goal
catch ex =>
if ex.isMaxHeartbeat || ex.isMaxRecDepth then
reportIssue! ex.toMessageData
pushFailure goal
return true
else
throw ex
def applyTac (x : GrindTactic) (goal : Goal) : M Bool := do
let go (goal : Goal) : M Bool := do
let some goals ← x goal | return false
pushGoals goals
return true
stepGuard go goal
def tryAssertNext : Goal → M Bool := applyTac assertNext
def tryEmatch : Goal → M Bool := applyTac ematchAndAssert
def trySplit : Goal → M Bool := applyTac splitNext
def tryArith : Goal → M Bool := applyTac Arith.check
def maxNumFailuresReached : M Bool := do
return (← get).failures.length ≥ (← getConfig).failures
partial def main (fallback : Fallback) : M Unit := do
repeat do
if (← get).stop then
return ()
let some goal ← getNext? |
return ()
if goal.inconsistent then
continue
if (← tryAssertNext goal) then
continue
if (← tryArith goal) then
continue
if (← tryEmatch goal) then
continue
if (← trySplit goal) then
continue
let goal ← GoalM.run' goal fallback
if goal.inconsistent || (← goal.mvarId.isAssigned) then
continue
pushFailure goal
end Solve
/--
Try to solve/close the given goals, and returns the ones that could not be solved.
-/
def solve (goals : List Goal) (fallback : Fallback) : GrindM (List Goal × List Goal) := do
let (_, s) ← Solve.main fallback |>.run { todo := goals }
return (s.failures.reverse, s.todo)
end Lean.Meta.Grind