@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Leonardo de Moura
55-/
66prelude
7+ import Lean.Meta.Tactic.Grind.ProveEq
78import Lean.Meta.Tactic.Grind.Arith.CommRing.RingId
89import Lean.Meta.Tactic.Grind.Arith.CommRing.Proof
910import Lean.Meta.Tactic.Grind.Arith.CommRing.DenoteExpr
@@ -282,6 +283,36 @@ def processNewEqImpl (a b : Expr) : GoalM Unit := do
282283 let p ← (ra.sub rb).toPolyM
283284 addNewEq (← mkEqCnstr p (.core a b ra rb))
284285
286+ private def pre (e : Expr) : GoalM Expr := do
287+ -- We must canonicalize because the instances generated by this module may not match
288+ -- the ones selected by the canonicalizer
289+ shareCommon (← canon e)
290+
291+ private def diseqToEq (a b : Expr) : RingM Unit := do
292+ -- Rabinowitsch transformation
293+ let gen := max (← getGeneration a) (← getGeneration b)
294+ let ring ← getRing
295+ let some fieldInst := ring.fieldInst? | unreachable!
296+ let e ← pre <| mkApp2 ring.subFn a b
297+ modifyRing fun s => { s with invSet := s.invSet.insert e }
298+ let eInv ← pre <| mkApp (← getRing).invFn?.get! e
299+ let lhs ← pre <| mkApp2 ring.mulFn e eInv
300+ internalize lhs gen none
301+ trace[grind.debug.ring.rabinowitsch] "{lhs}"
302+ pushEq lhs ring.one <| mkApp5 (mkConst ``Grind.CommRing.diseq_to_eq [ring.u]) ring.type fieldInst a b (← mkDiseqProof a b)
303+
304+ private def diseqZeroToEq (a b : Expr) : RingM Unit := do
305+ -- Rabinowitsch transformation for `b = 0` case
306+ let gen ← getGeneration a
307+ let ring ← getRing
308+ let some fieldInst := ring.fieldInst? | unreachable!
309+ modifyRing fun s => { s with invSet := s.invSet.insert a }
310+ let aInv ← pre <| mkApp (← getRing).invFn?.get! a
311+ let lhs ← pre <| mkApp2 ring.mulFn a aInv
312+ internalize lhs gen none
313+ trace[grind.debug.ring.rabinowitsch] "{lhs}"
314+ pushEq lhs ring.one <| mkApp4 (mkConst ``Grind.CommRing.diseq0_to_eq [ring.u]) ring.type fieldInst a (← mkDiseqProof a b)
315+
285316@[export lean_process_ring_diseq]
286317def processNewDiseqImpl (a b : Expr) : GoalM Unit := do
287318 let some ringId ← inSameRing? a b | return ()
@@ -290,6 +321,13 @@ def processNewDiseqImpl (a b : Expr) : GoalM Unit := do
290321 let some ra ← toRingExpr? a | return ()
291322 let some rb ← toRingExpr? b | return ()
292323 let p ← (ra.sub rb).toPolyM
324+ if (← isField) then
325+ unless p matches .num _ do
326+ if rb matches .num 0 then
327+ diseqZeroToEq a b
328+ else
329+ diseqToEq a b
330+ return ()
293331 addNewDiseq {
294332 lhs := a, rhs := b
295333 rlhs := ra, rrhs := rb
0 commit comments