|
| 1 | +import Lean |
| 2 | +import PfsProgs25.Unit13.MetaSolve |
| 3 | +open Lean Meta Elab Term Tactic |
| 4 | + |
| 5 | +/-! |
| 6 | +# Transitivity for `LE` on `Nat` |
| 7 | +
|
| 8 | +We *rewrite* inequalities for natural numbers using transitivity. Namely, if the goal is `a ≤ b` and we have `a ≤ c`, we can rewrite the goal to `c ≤ b` and similarly for `c ≤ b` and for just `a ≤ b`. |
| 9 | +-/ |
| 10 | +/- |
| 11 | +Nat.le_trans {n m k : ℕ} : n ≤ m → m ≤ k → n ≤ k |
| 12 | +-/ |
| 13 | +#check Nat.le_trans |
| 14 | + |
| 15 | +/- |
| 16 | +natLeExpr? (e : Expr) : MetaM (Option (Expr × Expr)) |
| 17 | +-/ |
| 18 | +#check natLeExpr? |
| 19 | + |
| 20 | +elab "nat_le_trans" t:term : tactic => |
| 21 | + withMainContext do |
| 22 | + match ← natLeExpr? <| ← getMainTarget with |
| 23 | + | none => throwError "Goal not an LE expression" |
| 24 | + | some (a, b) => |
| 25 | + let h ← Tactic.elabTerm t none |
| 26 | + match ← natLeExpr? <| ← inferType h with |
| 27 | + | none => throwError "Hypothesis not an LE expression" |
| 28 | + | some (c, d) => |
| 29 | + let checkLeft ← isDefEq a c |
| 30 | + let checkRight ← isDefEq b d |
| 31 | + if checkLeft && checkRight then |
| 32 | + closeMainGoal `nat_le_trans h |
| 33 | + else |
| 34 | + if checkLeft then |
| 35 | + -- the new goal is `d ≤ b` and |
| 36 | + -- the original goal follows from `h` and the new goal |
| 37 | + let newGoalType ← mkAppM ``Nat.le #[d, b] |
| 38 | + let newGoal ← mkFreshExprMVar newGoalType |
| 39 | + let goal ← getMainGoal |
| 40 | + let pf ← mkAppM ``Nat.le_trans #[h, newGoal] |
| 41 | + goal.assign pf |
| 42 | + replaceMainGoal [newGoal.mvarId!] |
| 43 | + else if checkRight then |
| 44 | + -- the new goal is `a ≤ c` and |
| 45 | + -- the original goal follows from `h` and the new goal |
| 46 | + let newGoalType ← mkAppM ``Nat.le #[a, c] |
| 47 | + let newGoal ← mkFreshExprMVar newGoalType |
| 48 | + let goal ← getMainGoal |
| 49 | + let pf ← mkAppM ``Nat.le_trans #[newGoal, h] |
| 50 | + goal.assign pf |
| 51 | + replaceMainGoal [newGoal.mvarId!] |
| 52 | + else |
| 53 | + throwError "Could not rewrite as neither ends match" |
| 54 | + |
| 55 | +example (a: Nat)(h : a ≤ 3): a ≤ 4 := by |
| 56 | + nat_le_trans h |
| 57 | + simp |
| 58 | + |
| 59 | + |
| 60 | +example (a: Nat)(h : 2 ≤ a): 0 ≤ a := by |
| 61 | + nat_le_trans h |
| 62 | + simp |
0 commit comments