-
Notifications
You must be signed in to change notification settings - Fork 234
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
772b606
commit 31d8db6
Showing
8 changed files
with
147 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/- | ||
Copyright (c) 2023 Patrick Massot. All rights reserved. | ||
Released under Apache 2.0 license as described in the file LICENSE. | ||
Authors: Moritz Doll, Mario Carneiro, Robert Y. Lewis, Patrick Massot | ||
-/ | ||
import Mathlib.Tactic.Qify | ||
import Mathlib.Data.Real.Basic | ||
|
||
/-! | ||
# `rify` tactic | ||
The `rify` tactic is used to shift propositions from `ℕ`, `ℤ` or `ℚ` to `ℝ`. | ||
Although less useful than its cousins `zify` and `qify`, it can be useful when your | ||
goal or context already involves real numbers. | ||
In the example below, assumption `hn` is about natural numbers, `hk` is about integers | ||
and involves casting a natural number to `ℤ`, and the conclusion is about real numbers. | ||
The proof uses `rify` to lift both assumptions to `ℝ` before calling `linarith`. | ||
``` | ||
import Mathlib.Tactic.Linarith | ||
import Mathlib.Tactic.Rify | ||
example {n : ℕ} {k : ℤ} (hn : 8 ≤ n) (hk : 2 * k ≤ n + 2) : | ||
(0 : ℝ) < n - k - 1 := by | ||
rify at hn hk | ||
linarith | ||
``` | ||
TODO: Investigate whether we should generalize this to other fields. | ||
-/ | ||
|
||
namespace Mathlib.Tactic.Rify | ||
|
||
open Lean | ||
open Lean.Meta | ||
open Lean.Parser.Tactic | ||
open Lean.Elab.Tactic | ||
|
||
/-- | ||
The `rify` tactic is used to shift propositions from `ℕ`, `ℤ` or `ℚ` to `ℝ`. | ||
Although less useful than its cousins `zify` and `qify`, it can be useful when your | ||
goal or context already involves real numbers. | ||
In the example below, assumption `hn` is about natural numbers, `hk` is about integers | ||
and involves casting a natural number to `ℤ`, and the conclusion is about real numbers. | ||
The proof uses `rify` to lift both assumptions to `ℝ` before calling `linarith`. | ||
``` | ||
example {n : ℕ} {k : ℤ} (hn : 8 ≤ n) (hk : 2 * k ≤ n + 2) : | ||
(0 : ℝ) < n - k - 1 := by | ||
rify at hn hk /- Now have hn : 8 ≤ (n : ℝ) hk : 2 * (k : ℝ) ≤ (n : ℝ) + 2-/ | ||
linarith | ||
``` | ||
`rify` makes use of the `@[zify_simps]`, `@[qify_simps]` and `@[rify_simps]` attributes to move | ||
propositions, and the `push_cast` tactic to simplify the `ℝ`-valued expressions. | ||
`rify` can be given extra lemmas to use in simplification. This is especially useful in the | ||
presence of nat subtraction: passing `≤` arguments will allow `push_cast` to do more work. | ||
``` | ||
example (a b c : ℕ) (h : a - b < c) (hab : b ≤ a) : a < b + c := by | ||
rify [hab] at h ⊢ | ||
linarith | ||
``` | ||
Note that `zify` or `qify` would work just as well in the above example (and `zify` is the natural | ||
choice since it is enough to get rid of the pathological `ℕ` subtraction). -/ | ||
syntax (name := rify) "rify" (simpArgs)? (location)? : tactic | ||
|
||
macro_rules | ||
| `(tactic| rify $[[$simpArgs,*]]? $[at $location]?) => | ||
let args := simpArgs.map (·.getElems) |>.getD #[] | ||
`(tactic| | ||
simp (config := {decide := false}) only [zify_simps, qify_simps, rify_simps, push_cast, $args,*] | ||
$[at $location]?) | ||
|
||
@[rify_simps] lemma rat_cast_eq (a b : ℚ) : a = b ↔ (a : ℝ) = (b : ℝ) := by simp | ||
@[rify_simps] lemma rat_cast_le (a b : ℚ) : a ≤ b ↔ (a : ℝ) ≤ (b : ℝ) := by simp | ||
@[rify_simps] lemma rat_cast_lt (a b : ℚ) : a < b ↔ (a : ℝ) < (b : ℝ) := by simp | ||
@[rify_simps] lemma rat_cast_ne (a b : ℚ) : a ≠ b ↔ (a : ℝ) ≠ (b : ℝ) := by simp | ||
|
||
-- See note [no_index around OfNat.ofNat] | ||
@[rify_simps] lemma ofNat_rat_real (a : ℕ) [a.AtLeastTwo] : | ||
((no_index (OfNat.ofNat a : ℚ)) : ℝ) = (OfNat.ofNat a : ℝ) := rfl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Mathlib.Tactic.Linarith | ||
import Mathlib.Tactic.Rify | ||
|
||
example {n : ℕ} {k : ℤ} (hn : 8 ≤ n) (hk : 2 * k ≤ n + 2) : | ||
(0 : ℝ) < n - k - 1 := by | ||
rify at hn hk | ||
linarith | ||
|
||
example {n : ℕ} {k : ℤ} (hn : 8 ≤ n) (hk : (2 : ℚ) * k ≤ n + 2) : | ||
(0 : ℝ) < n - k - 1 := by | ||
rify at hn hk | ||
linarith | ||
|
||
example (a b c : ℕ) (h : a - b < c) (hab : b ≤ a) : a < b + c := by | ||
rify [hab] at h ⊢ | ||
linarith | ||
|
||
example {n : ℕ} (h : 8 ≤ n) : (0 : ℝ) < n - 1 := by | ||
rify at h | ||
linarith | ||
|
||
example {n k : ℕ} (h : 2 * k ≤ n + 2) (h' : 8 ≤ n) : (0 : ℝ) ≤ 3 * n - 4 - 4 * k := by | ||
rify at * | ||
linarith | ||
|
||
example {n k : ℕ} (h₁ : 8 ≤ n) (h₂ : 2 * k > n) (h₃: k + 1 < n) : | ||
n - (k + 1) + 3 ≤ n := by | ||
rify [h₃] at * | ||
linarith | ||
|
||
example {n k : ℕ} (h₁ : 8 ≤ n) (h₂ : 2 * k > n) (h₃: k + 1 < n) : | ||
n - (n - (k + 1)) = k + 1 := by | ||
have f₁ : k + 1 ≤ n := by linarith | ||
have f₂ : n - (k + 1) ≤ n := by rify [f₁]; linarith | ||
rify [f₁, f₂] at * | ||
linarith |