@@ -6,6 +6,7 @@ Authors: Leonardo de Moura
66module
77prelude
88public import Lean.Meta.Tactic.Grind.Arith.CommRing.RingId
9+ public import Lean.Meta.Tactic.Grind.CheckResult
910import Lean.Meta.Tactic.Grind.ProveEq
1011import Lean.Meta.Tactic.Grind.Diseq
1112import Lean.Meta.Tactic.Grind.Arith.Util
@@ -485,29 +486,31 @@ abbrev PropagateEqMap := Std.HashMap (Int × Poly) (Expr × RingExpr)
485486/--
486487Propagates implied equalities.
487488-/
488- private def propagateEqs : RingM Unit := do
489- if (← isInconsistent) then return ()
489+ private def propagateEqs : RingM Bool := do
490+ if (← isInconsistent) then return false
490491 /-
491492 This is a very simple procedure that does not use any indexing data-structure.
492493 We don't even cache the simplified polynomials.
493494 TODO: optimize
494495 TODO: support for semiring
495496 -/
496- let mut map : PropagateEqMap := {}
497- for a in (← getRing).vars do
498- if (← checkMaxSteps) then return ()
499- let some ra ← toRingExpr? a | unreachable!
500- map ← process map a ra
501- for (a, ra) in (← getCommRing).denoteEntries do
502- if (← checkMaxSteps) then return ()
503- map ← process map a ra
497+ let go : StateT (Bool × PropagateEqMap) RingM Unit := do
498+ for a in (← getRing).vars do
499+ if (← checkMaxSteps) then return ()
500+ let some ra ← toRingExpr? a | unreachable!
501+ process a ra
502+ for (a, ra) in (← getCommRing).denoteEntries do
503+ if (← checkMaxSteps) then return ()
504+ process a ra
505+ let (_, (propagated, _)) ← go.run (false , {})
506+ return propagated
504507where
505- process (map : PropagateEqMap) ( a : Expr) (ra : RingExpr) : RingM PropagateEqMap := do
508+ process (a : Expr) (ra : RingExpr) : StateT (Bool × PropagateEqMap) RingM Unit := do
506509 let d : PolyDerivation := .input (← ra.toPolyM)
507510 let d ← d.simplify
508511 let k := d.getMultiplier
509512 trace_goal[grind.debug.ring.impEq] "{a}, {k}, {← d.p.denoteExpr}"
510- if let some (b, rb) := map [(k, d.p)]? then
513+ if let some (b, rb) := (← get). 2 [(k, d.p)]? then
511514 -- TODO: use `isEqv` more effectively
512515 unless (← isEqv a b) do
513516 let p ← (ra.sub rb).toPolyM
@@ -518,40 +521,44 @@ where
518521 -- Given the multiplier `k' = d.getMultiplier`, we have that `k*(a - b) = 0`,
519522 -- but we cannot eliminate the `k` because we don't have `noZeroDivisors`.
520523 trace_goal[grind.ring.impEq] "skip: {← mkEq a b}, k: {k}, noZeroDivisors: false"
521- return map.insert (k, d.p) (a, ra)
524+ modify fun (propagated, map) => (propagated, map.insert (k, d.p) (a, ra))
525+ return ()
522526 trace_goal[grind.ring.impEq] "{← mkEq a b}, {k}, {← p.denoteExpr}"
523527 propagateEq a b ra rb d
524- return map
528+ modify fun s => ( true , s. 2 )
525529 else
526- return map.insert (k, d.p) (a, ra)
530+ modify fun (propagated, map) => (propagated, map .insert (k, d.p) (a, ra) )
527531
528- def checkRing : RingM Bool := do
529- unless (← needCheck) do return false
532+ def checkRing : RingM CheckResult := do
533+ unless (← needCheck) do return .none
530534 trace_goal[grind.debug.ring.check] "{(← getRing).type}"
531535 repeat
532536 checkSystem "ring"
533537 let some c ← getNext? | break
534538 trace_goal[grind.debug.ring.check] "{← c.denoteExpr}"
535539 c.addToBasis
536- if (← isInconsistent) then return true
537- if (← checkMaxSteps) then return true
540+ if (← isInconsistent) then return .closed
541+ if (← checkMaxSteps) then return .progress
538542 checkDiseqs
539- propagateEqs
543+ if (← propagateEqs) then return .propagated
540544 modifyCommRing fun s => { s with recheck := false }
541- return true
545+ return .progress
542546
543- def check : GoalM Bool := do profileitM Exception "grind ring" (← getOptions) do
544- if (← checkMaxSteps) then return false
545- let mut progress := false
547+ def check : GoalM CheckResult := do profileitM Exception "grind ring" (← getOptions) do
548+ if (← checkMaxSteps) then return .none
549+ let mut result : CheckResult := .none
546550 checkInvariants
547551 try
548552 for ringId in *...(← get').rings.size do
549553 let r ← RingM.run ringId checkRing
550- progress := progress || r
554+ result := result.join r
551555 if (← isInconsistent) then
552- return true
553- return progress
556+ return .closed
557+ return result
554558 finally
555559 checkInvariants
556560
561+ def check' : GoalM Bool :=
562+ return (← check) != .none
563+
557564end Lean.Meta.Grind.Arith.CommRing
0 commit comments