Skip to content

Commit 6253518

Browse files
committed
Merge branch 'nightly-with-mathlib' of https://github.com/leanprover/lean4 into joachim/csup-prop
2 parents b3c9a07 + 5bd331e commit 6253518

File tree

6 files changed

+189
-16
lines changed

6 files changed

+189
-16
lines changed

src/Init/Grind/Ring/CommSolver.lean

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,53 @@ where
180180
else
181181
.mult { x := pw₁.x, k := pw₁.k + pw₂.k } (go fuel m₁ m₂)
182182

183+
noncomputable def Mon.mul_k : Mon → Mon → Mon :=
184+
Nat.rec
185+
(fun m₁ m₂ => concat m₁ m₂)
186+
(fun _ ih m₁ m₂ =>
187+
Mon.rec (t := m₂)
188+
m₁
189+
(fun pw₂ m₂' _ => Mon.rec (t := m₁)
190+
m₂
191+
(fun pw₁ m₁' _ =>
192+
Bool.rec (t := pw₁.varLt pw₂)
193+
(Bool.rec (t := pw₂.varLt pw₁)
194+
(.mult { x := pw₁.x, k := Nat.add pw₁.k pw₂.k } (ih m₁' m₂'))
195+
(.mult pw₂ (ih (.mult pw₁ m₁') m₂')))
196+
(.mult pw₁ (ih m₁' (.mult pw₂ m₂'))))))
197+
hugeFuel
198+
199+
theorem Mon.mul_k_eq_mul : Mon.mul_k m₁ m₂ = Mon.mul m₁ m₂ := by
200+
unfold mul_k mul
201+
generalize hugeFuel = fuel
202+
fun_induction mul.go
203+
· rfl
204+
· rfl
205+
case case3 m₂ _ =>
206+
cases m₂
207+
· contradiction
208+
· dsimp
209+
case case4 fuel pw₁ m₁ pw₂ m₂ h ih =>
210+
dsimp only
211+
rw [h]
212+
dsimp only
213+
rw [ih]
214+
case case5 fuel pw₁ m₁ pw₂ m₂ h₁ h₂ ih =>
215+
dsimp only
216+
rw [h₁]
217+
dsimp only
218+
rw [h₂]
219+
dsimp only
220+
rw [ih]
221+
case case6 fuel pw₁ m₁ pw₂ m₂ h₁ h₂ ih =>
222+
dsimp only
223+
rw [h₁]
224+
dsimp only
225+
rw [h₂]
226+
dsimp only
227+
rw [ih]
228+
rfl
229+
183230
def Mon.mul_nc (m₁ m₂ : Mon) : Mon :=
184231
match m₁ with
185232
| .unit => m₂
@@ -190,6 +237,28 @@ def Mon.degree : Mon → Nat
190237
| .unit => 0
191238
| .mult pw m => pw.k + degree m
192239

240+
noncomputable def Mon.degree_k : Mon → Nat :=
241+
Nat.rec
242+
(fun m => m.degree)
243+
(fun _ ih m =>
244+
Mon.rec (t := m)
245+
0
246+
(fun pw m' _ => Nat.add pw.k (ih m')))
247+
hugeFuel
248+
249+
theorem Mon.degree_k_eq_degree : Mon.degree_k m = Mon.degree m := by
250+
unfold degree_k
251+
generalize hugeFuel = fuel
252+
induction fuel generalizing m with
253+
| zero => rfl
254+
| succ fuel ih =>
255+
conv => rhs; unfold degree
256+
split
257+
· rfl
258+
· dsimp only
259+
rw [← ih]
260+
rfl
261+
193262
def Var.revlex (x y : Var) : Ordering :=
194263
bif x.blt y then .gt
195264
else bif y.blt x then .lt
@@ -270,7 +339,7 @@ noncomputable def Mon.grevlex_k (m₁ m₂ : Mon) : Ordering :=
270339
Bool.rec
271340
(Bool.rec .gt .lt (Nat.blt m₁.degree m₂.degree))
272341
(revlex_k m₁ m₂)
273-
(Nat.beq m₁.degree m₂.degree)
342+
(Nat.beq m₁.degree_k m₂.degree_k)
274343

275344
theorem Mon.revlex_k_eq_revlex (m₁ m₂ : Mon) : m₁.revlex_k m₂ = m₁.revlex m₂ := by
276345
unfold revlex_k revlex
@@ -302,18 +371,18 @@ theorem Mon.grevlex_k_eq_grevlex (m₁ m₂ : Mon) : m₁.grevlex_k m₂ = m₁.
302371
next h =>
303372
have h₁ : Nat.blt m₁.degree m₂.degree = true := by simp [h]
304373
have h₂ : Nat.beq m₁.degree m₂.degree = false := by rw [← Bool.not_eq_true, Nat.beq_eq]; omega
305-
simp [h₁, h₂]
374+
simp [degree_k_eq_degree, h₁, h₂]
306375
next h =>
307376
split
308377
next h' =>
309378
have h₂ : Nat.beq m₁.degree m₂.degree = true := by rw [Nat.beq_eq, h']
310-
simp [h₂]
379+
simp [degree_k_eq_degree, h₂]
311380
next h' =>
312381
have h₁ : Nat.blt m₁.degree m₂.degree = false := by
313382
rw [← Bool.not_eq_true, Nat.blt_eq]; assumption
314383
have h₂ : Nat.beq m₁.degree m₂.degree = false := by
315384
rw [← Bool.not_eq_true, Nat.beq_eq]; assumption
316-
simp [h₁, h₂]
385+
simp [degree_k_eq_degree, h₁, h₂]
317386

318387
inductive Poly where
319388
| num (k : Int)
@@ -481,7 +550,7 @@ noncomputable def Poly.mulMon_k (k : Int) (m : Mon) (p : Poly) : Poly :=
481550
(Bool.rec
482551
(Poly.rec
483552
(fun k' => Bool.rec (.add (Int.mul k k') m (.num 0)) (.num 0) (Int.beq' k' 0))
484-
(fun k' m' _ ih => .add (Int.mul k k') (m.mul m') ih)
553+
(fun k' m' _ ih => .add (Int.mul k k') (m.mul_k m') ih)
485554
p)
486555
(p.mulConst_k k)
487556
(Mon.beq' m .unit))
@@ -511,7 +580,7 @@ noncomputable def Poly.mulMon_k (k : Int) (m : Mon) (p : Poly) : Poly :=
511580
next =>
512581
have h : Int.beq' k 0 = false := by simp [*]
513582
simp [h]
514-
next ih => simp [← ih]
583+
next ih => simp [← ih, Mon.mul_k_eq_mul]
515584

516585
def Poly.mulMon_nc (k : Int) (m : Mon) (p : Poly) : Poly :=
517586
bif k == 0 then

src/Init/Notation.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ Position reporting:
842842
`#guard_msgs` appears.
843843
- `positions := false` does not report position info.
844844
845-
For example, `#guard_msgs (error, drop all) in cmd` means to check warnings and drop
845+
For example, `#guard_msgs (error, drop all) in cmd` means to check errors and drop
846846
everything else.
847847
848848
The command elaborator has special support for `#guard_msgs` for linting.

src/Lean/Meta/Tactic/Grind/Parser.lean

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,102 @@ def grindPatternCnstrs : Parser := leading_parser "where " >> many1Indent (ppLin
3535
/-!
3636
Builtin parsers for `grind` related commands
3737
-/
38+
39+
/--
40+
The `grind_pattern` command can be used to manually select a pattern for theorem instantiation.
41+
Enabling the option `trace.grind.ematch.instance` causes `grind` to print a trace message for each
42+
theorem instance it generates, which can be helpful when determining patterns.
43+
44+
When multiple patterns are specified together, all of them must match in the current context before
45+
`grind` attempts to instantiate the theorem. This is referred to as a *multi-pattern*.
46+
This is useful for theorems such as transitivity rules, where multiple premises must be simultaneously
47+
present for the rule to apply.
48+
49+
In the following example, `R` is a transitive binary relation over `Int`.
50+
```
51+
opaque R : Int → Int → Prop
52+
axiom Rtrans {x y z : Int} : R x y → R y z → R x z
53+
```
54+
To use the fact that `R` is transitive, `grind` must already be able to satisfy both premises.
55+
This is represented using a multi-pattern:
56+
```
57+
grind_pattern Rtrans => R x y, R y z
58+
59+
example {a b c d} : R a b → R b c → R c d → R a d := by
60+
grind
61+
```
62+
The multi-pattern `R x y`, `R y z` instructs `grind` to instantiate `Rtrans` only when both `R x y`
63+
and `R y z` are available in the context. In the example, `grind` applies `Rtrans` to derive `R a c`
64+
from `R a b` and `R b c`, and can then repeat the same reasoning to deduce `R a d` from `R a c` and
65+
`R c d`.
66+
67+
You can add constraints to restrict theorem instantiation. For example:
68+
```
69+
grind_pattern extract_extract => (as.extract i j).extract k l where
70+
as =/= #[]
71+
```
72+
The constraint instructs `grind` to instantiate the theorem only if `as` is **not** definitionally equal
73+
to `#[]`.
74+
75+
## Constraints
76+
77+
- `x =/= term`: The term bound to `x` (one of the theorem parameters) is **not** definitionally equal to `term`.
78+
The term may contain holes (i.e., `_`).
79+
80+
- `x =?= term`: The term bound to `x` is definitionally equal to `term`.
81+
The term may contain holes (i.e., `_`).
82+
83+
- `size x < n`: The term bound to `x` has size less than `n`. Implicit arguments
84+
and binder types are ignored when computing the size.
85+
86+
- `depth x < n`: The term bound to `x` has depth less than `n`.
87+
88+
- `is_ground x`: The term bound to `x` does not contain local variables or meta-variables.
89+
90+
- `is_value x`: The term bound to `x` is a value. That is, it is a constructor fully applied to value arguments,
91+
a literal (`Nat`, `Int`, `String`, etc.), or a lambda `fun x => t`.
92+
93+
- `is_strict_value x`: Similar to `is_value`, but without lambdas.
94+
95+
- `gen < n`: The theorem instance has generation less than `n`. Recall that each term is assigned a
96+
generation, and terms produced by theorem instantiation have a generation that is one greater than
97+
the maximal generation of all the terms used to instantiate the theorem. This constraint complements
98+
the `gen` option available in `grind`.
99+
100+
- `max_insts < n`: A new instance is generated only if less than `n` instances have been generated so far.
101+
102+
- `guard e`: The instantiation is delayed until `grind` learns that `e` is `true` in this state.
103+
104+
- `check e`: Similar to `guard e`, but `grind` checks whether `e` is implied by its current state by
105+
assuming `¬ e` and trying to deduce an inconsistency.
106+
107+
## Example
108+
109+
Consider the following example where `f` is a monotonic function
110+
```
111+
opaque f : Nat → Nat
112+
axiom fMono : x ≤ y → f x ≤ f y
113+
```
114+
and you want to instruct `grind` to instantiate `fMono` for every pair of terms `f x` and `f y` when
115+
`x ≤ y` and `x` is **not** definitionally equal to `y`. You can use
116+
```
117+
grind_pattern fMono => f x, f y where
118+
guard x ≤ y
119+
x =/= y
120+
```
121+
Then, in the following example, only three instances are generated.
122+
```
123+
/--
124+
trace: [grind.ematch.instance] fMono: a ≤ f a → f a ≤ f (f a)
125+
[grind.ematch.instance] fMono: f a ≤ f (f a) → f (f a) ≤ f (f (f a))
126+
[grind.ematch.instance] fMono: a ≤ f (f a) → f a ≤ f (f (f a))
127+
-/
128+
#guard_msgs in
129+
example : f b = f c → a ≤ f a → f (f a) ≤ f (f (f a)) := by
130+
set_option trace.grind.ematch.instance true in
131+
grind
132+
```
133+
-/
38134
@[builtin_command_parser] def grindPattern := leading_parser
39135
Term.attrKind >> "grind_pattern " >> ident >> darrow >> sepBy1 termParser "," >> optional grindPatternCnstrs
40136

src/Lean/Meta/Tactic/Simp/Main.lean

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public import Lean.Meta.Tactic.Simp.Diagnostics
1212
public import Lean.Meta.Match.Value
1313
public import Lean.Util.CollectLooseBVars
1414
import Lean.PrettyPrinter
15+
import Lean.ExtraModUses
1516

1617
public section
1718

@@ -1069,15 +1070,29 @@ def simpImpl (e : Expr) : SimpM Result := withIncRecDepth do
10691070
else
10701071
x
10711072

1073+
/--
1074+
For `rfl` theorems and simprocs, there might not be an explicit reference in the proof term, so
1075+
we record (all non-builtin) usages explicitly.
1076+
-/
1077+
private def recordSimpUses (s : State) : MetaM Unit := do
1078+
for (thm, _) in s.usedTheorems.map do
1079+
if let .decl declName .. := thm then
1080+
if !(← isBuiltinSimproc declName) then
1081+
recordExtraModUseFromDecl (isMeta := false) declName
1082+
10721083
def mainCore (e : Expr) (ctx : Context) (s : State := {}) (methods : Methods := {}) : MetaM (Result × State) := do
1073-
SimpM.run ctx s methods <| withCatchingRuntimeEx <| simp e
1084+
let (r, s) ← SimpM.run ctx s methods <| withCatchingRuntimeEx <| simp e
1085+
recordSimpUses s
1086+
return (r, s)
10741087

10751088
def main (e : Expr) (ctx : Context) (stats : Stats := {}) (methods : Methods := {}) : MetaM (Result × Stats) := do
10761089
let (r, s) ← mainCore e ctx { stats with } methods
10771090
return (r, { s with })
10781091

10791092
def dsimpMainCore (e : Expr) (ctx : Context) (s : State := {}) (methods : Methods := {}) : MetaM (Expr × State) := do
1080-
SimpM.run ctx s methods <| withCatchingRuntimeEx <| dsimp e
1093+
let (r, s) ← SimpM.run ctx s methods <| withCatchingRuntimeEx <| dsimp e
1094+
recordSimpUses s
1095+
return (r, s)
10811096

10821097
def dsimpMain (e : Expr) (ctx : Context) (stats : Stats := {}) (methods : Methods := {}) : MetaM (Expr × Stats) := do
10831098
let (r, s) ← dsimpMainCore e ctx { stats with } methods

src/Lean/Meta/Tactic/Simp/Types.lean

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public import Lean.Meta.Eqns
1212
public import Lean.Meta.Tactic.Simp.SimpTheorems
1313
public import Lean.Meta.Tactic.Simp.SimpCongrTheorems
1414
import Lean.Meta.Tactic.Replace
15-
import Lean.ExtraModUses
1615

1716
public section
1817

@@ -881,11 +880,6 @@ def SimpM.run (ctx : Context) (s : State := {}) (methods : Methods := {}) (k : S
881880
trace[Meta.Tactic.simp.numSteps] "{s.numSteps}"
882881
let stats ← updateUsedSimpsWithZetaDelta ctx { s with }
883882
let s := { s with diag := stats.diag, usedTheorems := stats.usedTheorems }
884-
for (thm, _) in s.usedTheorems.map do
885-
if let .decl declName .. := thm then
886-
-- for `rfl` theorems and simprocs, there might not be an explicit reference in the proof
887-
-- term
888-
recordExtraModUseFromDecl (isMeta := false) declName
889883
return (r, s)
890884

891885
end Simp

tests/lean/run/grind_ring_5.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
module
22
open Lean.Grind
33

4-
54
example {α} [CommRing α] [IsCharP α 0] (d t c : α) (d_inv PSO3_inv : α)
65
40 : d^2 * (d + t - d * t - 2) *
76
(d + t + d * t) = 0)

0 commit comments

Comments
 (0)