Previously, the tactic state shown at `decreasing_by` would leak lots of details about the translation, and mention `invImage`, `PSigma` etc. This is not nice. So this introduces `clean_wf`, which is like `simp_wf` but using `simp`'s `only` mode, and runs this unconditionally. This should clean up the goal to a reasonable extent. Previously `simp_wf` was an unrestricted `simp […]` call, but we probably don’t want arbitrary simplification to happen at this point, so this now became `simp only` call. For backwards compatibility, `decreasing_with` begins with `try simp`. The `simp_wf` tactic is still available to not break too much existing code; it’s docstring suggests to no longer use it. With `set_option cleanDecreasingByGoal false` one can disable the use of `clean_wf`. I hope this is only needed for debugging and understanding. Migration advise: If your `decreasing_by` proof begins with `simp_wf`, either remove that (if the proof still goes through), or replace with `simp`. I am a bit anxious about running even `simp only` unconditionally here, as it may do more than some user might want, e.g. because of options like `zetaDelta := true`. We'll see if we need to reign in this tactic some more. I wonder if in corner cases the `simp_wf` tactic might be able to close the goal, and if that is a problem. If so, we may have to promote simp’s internal `mayCloseGoal` parameter to a simp configuration option and use that here. fixes #4928
68 lines
1.2 KiB
Text
68 lines
1.2 KiB
Text
mutual
|
|
def g (i j : Nat) : Nat :=
|
|
if i < 5 then 0 else
|
|
match j with
|
|
| Nat.zero => 1
|
|
| Nat.succ j => h i j
|
|
termination_by (i + j, 0)
|
|
decreasing_by
|
|
· apply Prod.Lex.left
|
|
apply Nat.lt_succ_self
|
|
|
|
def h (i j : Nat) : Nat :=
|
|
match j with
|
|
| 0 => g i 0
|
|
| Nat.succ j => g i j
|
|
termination_by (i + j, 1)
|
|
decreasing_by
|
|
· apply Prod.Lex.right
|
|
decide
|
|
· apply Prod.Lex.left
|
|
apply Nat.lt_succ_self
|
|
end
|
|
|
|
/-- info: g.eq_1 (i : Nat) : g i Nat.zero = if i < 5 then 0 else 1 -/
|
|
#guard_msgs in
|
|
#check g.eq_1
|
|
|
|
/-- info: g.eq_2 (i j_2 : Nat) : g i j_2.succ = if i < 5 then 0 else h i j_2 -/
|
|
#guard_msgs in
|
|
#check g.eq_2
|
|
|
|
/--
|
|
info: g.eq_def (i j : Nat) :
|
|
g i j =
|
|
if i < 5 then 0
|
|
else
|
|
match j with
|
|
| Nat.zero => 1
|
|
| j.succ => h i j
|
|
-/
|
|
#guard_msgs in
|
|
#check g.eq_def
|
|
|
|
/-- error: unknown identifier 'g.eq_3' -/
|
|
#guard_msgs in
|
|
#check g.eq_3
|
|
|
|
/-- info: h.eq_1 (i : Nat) : h i 0 = g i 0 -/
|
|
#guard_msgs in
|
|
#check h.eq_1
|
|
|
|
/-- info: h.eq_2 (i j_2 : Nat) : h i j_2.succ = g i j_2 -/
|
|
#guard_msgs in
|
|
#check h.eq_2
|
|
|
|
/--
|
|
info: h.eq_def (i j : Nat) :
|
|
h i j =
|
|
match j with
|
|
| 0 => g i 0
|
|
| j.succ => g i j
|
|
-/
|
|
#guard_msgs in
|
|
#check h.eq_def
|
|
|
|
/-- error: unknown identifier 'h.eq_3' -/
|
|
#guard_msgs in
|
|
#check h.eq_3
|