Zulip Chat Archive
Stream: new members
Topic: rw vs simp | default arguments for hypothesis
Tobias Grosser (Aug 09 2024 at 21:08):
I am currently playing with the following code:
lemma pow_pred_mul {x y : Nat } (h : 0 < y := by omega) :
x ^ (y - 1) * x = x ^ y := by
simp only [← pow_succ, gt_iff_lt, ne_eq, not_false_eq_true]
rw [Nat.sub_add_cancel]
omega
theorem this_works {y : Nat} (h : 0 < y) :
2 ^ (y - 1) * 2 = 2 ^ y := by
simp [pow_pred_mul h] -- This works
theorem this_does_not_work {x y : Nat} (h : 0 < y) :
2 ^ (y - 1) * 2 = 2 ^ y := by
simp [pow_pred_mul] -- This does not work
theorem this_also_works {x y : Nat} (h : 0 < y) :
2 ^ (y - 1) * 2 = 2 ^ y := by
rw [pow_pred_mul] -- this_also_works
I would like for the this_does_not_work
example to work the same way as the this_also_works
example. Meaning, i would have hoped that simp could automatically pick up the correct hypothesis. I guess there is a reason it does not do this. Could someone help me with some background here?
Julian Berman (Aug 09 2024 at 21:59):
I don't know enough to provide said context (I assume you're asking why using simp
doesn't try to fill in the hypothesis needed using your default discharger that you wrote in pow_pred_mul
, if I recall the terminology correctly) -- just to note though, simp [h, pow_pred_mul]
works as well, if that happens to suit you.
Tobias Grosser (Aug 09 2024 at 22:15):
Ah, this is interesting, Therefore simp [h, pow_pred_mul]
as well as simp_all [pow_pred_mul]
also work.
Tobias Grosser (Aug 09 2024 at 22:18):
I guess my conclusion is then that it is not best-practice to include the := omega in the @[simp]
theorem, as simp can add h
automatically as long as its part of the simp set. To get it there I should use one of the three, simp [h]
, simp [*]
, or simp_all
.
Tobias Grosser (Aug 09 2024 at 22:19):
Thank you, this input was quite useful.
Julian Berman (Aug 09 2024 at 22:35):
I think that sounds right based on what I've seen, though I suspect it's still an interesting question to ask from someone who knows more about how the simplifier works as to why simp -- when it encounters a lemma which has a default discharger -- can't try applying the lemma and seeing whether it type checks after the default argument gets filled in. The answer seems like it may be "performance" I guess?, but I'd still be curious to hear.
Julian Berman (Aug 09 2024 at 22:36):
Maybe it's not too nice considering whatever tactic is there can potentially do arbitrarily slow amounts of work?
Tomas Skrivan (Aug 09 2024 at 22:51):
You can specify custom discharger i.e. a tactic that tries to close assumptions of simp theorems. In this example it is sufficient to use assumption
theorem works_with_assumption {x y : Nat} (h : 0 < y) :
2 ^ (y - 1) * 2 = 2 ^ y := by
simp (disch:=assumption) [pow_pred_mul]
you can also directly call apply h
theorem works_with_apply {x y : Nat} (h : 0 < y) :
2 ^ (y - 1) * 2 = 2 ^ y := by
simp (disch:=apply h) [pow_pred_mul]
When the hypothesis h
does not fit the exactly the assumption you might have to use more powerful tactic like aesop
theorem works_with_aesop {x y : Nat} (h : 0 < y) :
2 ^ (y^2 - 1) * 2 = 2 ^ (y^2) := by
simp (disch:=aesop) [pow_pred_mul]
To diagnose this kind of problem it is useful to use option
set_option trace.Meta.Tactic.simp.discharge true
which on this_does_not_work
produces this trace:
trace
Julian Berman (Aug 09 2024 at 22:58):
But that discharger in simp's config is "global" to all the lemmas simp tries to use obviously right? In theory might each lemma not know best as to what tactics are best suited to discharging their hypotheses automatically?
Tomas Skrivan (Aug 09 2024 at 23:23):
Yes it is a global discharger for all lemmas.
On my to-do list is to write a tactic/discharger that executes the tactic provided by auto parameter which would exactly run the most appropriate tactic for a particular argument of a particular theorem.
Tomas Skrivan (Aug 09 2024 at 23:29):
This would of course require to go over all the theorems and add appropriate auto parameters.
Tobias Grosser (Aug 09 2024 at 23:31):
I wonder if one could somehow do this using some kind of matching machinery? Or somehow derive these from data than doing it all manually.
Tobias Grosser (Aug 09 2024 at 23:31):
Or maybe a mix. This sounds definitely interesting.
Tomas Skrivan (Aug 09 2024 at 23:33):
I often run (disch:=aesop)
and just rely that aesop
is smart enough to pick what ever strategy it thinks is the best.
Last updated: May 02 2025 at 03:31 UTC