feat: add support for negation at simpCnstr?

This commit is contained in:
Leonardo de Moura 2022-02-25 18:30:09 -08:00
parent 5030e613a2
commit 41a5c2bce4
3 changed files with 56 additions and 2 deletions

View file

@ -537,6 +537,24 @@ def mkSub (a b : Expr) : MetaM Expr := mkBinaryOp ``HSub ``HSub.hSub a b
/-- Return `a * b` using a heterogeneous `*`. This method assumes `a` and `b` have the same type. -/
def mkMul (a b : Expr) : MetaM Expr := mkBinaryOp ``HMul ``HMul.hMul a b
/--
Return `a r b`, where `r` has name `rName` and is implemented using the typeclass `className`.
This method assumes `a` and `b` have the same type.
Examples of supported clases: `LE` and `LT`.
We use heterogeneous operators to ensure we have a uniform representation.
-/
private def mkBinaryRel (className : Name) (rName : Name) (a b : Expr) : MetaM Expr := do
let aType ← inferType a
let u ← getDecLevel aType
let inst ← synthInstance (mkApp (mkConst className [u]) aType)
return mkApp4 (mkConst rName [u]) aType inst a b
/-- Return `a ≤ b`. This method assumes `a` and `b` have the same type. -/
def mkLE (a b : Expr) : MetaM Expr := mkBinaryRel ``LE ``LE.le a b
/-- Return `a < b`. This method assumes `a` and `b` have the same type. -/
def mkLT (a b : Expr) : MetaM Expr := mkBinaryRel ``LT ``LT.lt a b
builtin_initialize registerTraceClass `Meta.appBuilder
end Lean.Meta

View file

@ -154,7 +154,7 @@ def toContextExpr (ctx : Array Expr) : MetaM Expr := do
def reflTrue : Expr :=
mkApp2 (mkConst ``Eq.refl [levelOne]) (mkConst ``Bool) (mkConst ``Bool.true)
def simpCnstr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
def simpCnstrPos? (e : Expr) : MetaM (Option (Expr × Expr)) := do
let (some c, ctx) ← ToLinear.run (ToLinear.toLinearCnstr? e) | return none
let c₁ := c.toPoly
let c₂ := c₁.norm
@ -172,4 +172,32 @@ def simpCnstr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
else
return none
def simpCnstr? (e : Expr) : MetaM (Option (Expr × Expr)) := do
if let some arg := e.not? then
let mut eNew? := none
let mut thmName := Name.anonymous
if arg.isAppOfArity ``LE.le 4 then
eNew? := some (← mkLE (← mkAdd (arg.getArg! 3) (mkNatLit 1)) (arg.getArg! 2))
thmName := ``Nat.not_le_eq
else if arg.isAppOfArity ``GE.ge 4 then
eNew? := some (← mkLE (← mkAdd (arg.getArg! 2) (mkNatLit 1)) (arg.getArg! 3))
thmName := ``Nat.not_ge_eq
else if arg.isAppOfArity ``LT.lt 4 then
eNew? := some (← mkLE (arg.getArg! 3) (arg.getArg! 2))
thmName := ``Nat.not_lt_eq
else if arg.isAppOfArity ``GT.gt 4 then
eNew? := some (← mkLE (arg.getArg! 2) (arg.getArg! 3))
thmName := ``Nat.not_gt_eq
if let some eNew := eNew? then
if let some (eNew', h₂) ← simpCnstrPos? eNew then
let h₁ := mkApp2 (mkConst thmName) (arg.getArg! 2) (arg.getArg! 3)
let h := mkApp6 (mkConst ``Eq.trans [levelOne]) (mkSort levelZero) e eNew eNew' h₁ h₂
return some (eNew', h)
else
return none
else
return none
else
simpCnstrPos? e
end Lean.Meta.Linear.Nat

View file

@ -3,7 +3,7 @@ import Lean
open Lean in open Lean.Meta in
def test (declName : Name) : MetaM Unit := do
let info ← getConstInfo declName
forallTelescopeReducing info.type fun _ e => do
forallTelescope info.type fun _ e => do
let some (e', p) ← Linear.simpCnstr? e | throwError "failed to simplify{indentExpr e}"
check p
unless (← isDefEq (← inferType p) (← mkEq e e')) do
@ -20,6 +20,10 @@ axiom ex7 (a b : Nat) : a + a ≤ 8 + a + a + b
axiom ex8 (a b c d : Nat) : b + a + c + d ≤ a + b + a + b
axiom ex9 (a b : Nat) : a + b + 1 + a > b + 4 + a
axiom ex10 (a b : Nat) : a + b + 1 + a ≥ b + 4 + a
axiom ex11 (a b : Nat) : ¬ (a + b + 1 + a < b + 4 + a)
axiom ex12 (a b : Nat) : ¬ (a + b + 1 + a > b + 4 + a)
axiom ex13 (a b : Nat) : ¬ (a + b + 1 + a ≤ b + 4 + a)
axiom ex14 (a b : Nat) : ¬ (a + b + 1 + a ≥ b + 4 + a)
#eval test ``ex1
#eval test ``ex2
@ -31,3 +35,7 @@ axiom ex10 (a b : Nat) : a + b + 1 + a ≥ b + 4 + a
#eval test ``ex8
#eval test ``ex9
#eval test ``ex10
#eval test ``ex11
#eval test ``ex12
#eval test ``ex13
#eval test ``ex14