Zulip Chat Archive

Stream: Is there code for X?

Topic: more inductions for int


Joachim Breitner (Mar 21 2022 at 22:18):

I (think I) currently need the int-equivalents of nat.le_induction and nat.decreasing_induction. I’d add them unless someone tells me that my abilities to search for existing lemmas have proven insufficient.

Joachim Breitner (Mar 21 2022 at 22:36):

I guess they are just specializations of https://leanprover-community.github.io/mathlib_docs/data/int/basic.html#int.induction_on%27

Eric Wieser (Mar 21 2022 at 22:57):

Ouch, that has nasty equation lemmas

Patrick Johnson (Mar 22 2022 at 00:07):

Both lemmas follow directly from int.induction_on'

I think the bias is against adding new induction principles if they follow from existing ones (see this for example).

Johan Commelin (Mar 22 2022 at 06:34):

In LTE I recently added

-- src/for_mathlib/triangle_shift.lean L426L433
@[elab_as_eliminator] protected lemma _root_.int.induction_on_iff {p :   Prop}
  (i : ) (hz : p 0) (h :  i : , p i  p (i + 1)) : p i :=
begin
  induction i using int.induction_on with i IH i IH,
  { exact hz },
  { rwa  h },
  { rw h, simpa only [sub_add_cancel], }
end

Kevin Buzzard (Mar 22 2022 at 08:07):

Another thing that's missing is something which is definitionally nat.rec but uses +1 instead of succ. I would like to see this one in mathlib but it definitely follows from something which is already there :-)

Eric Wieser (Mar 22 2022 at 09:19):

match n with | 0 := _ | (n + 1) := _ end is one way to spell that recursor, but I guess that's annoying

Michael Stoll (Mar 22 2022 at 09:39):

I have written a "multiplicative induction" principle, since I needed it for my work on the Hilbert symbol:

/-!
### Establish an induction principle for multiplicatively closed properties

If `P : ℕ → Prop` satisfies `P 0`, `P 1`, `P p` for every prime number `p`
and `∀ (m n : ℕ), P m → P n → P (m*n)`, then `P n` holds for all `n : ℕ`.

Similarly for `P : ℤ → Prop`, with `P (-1)` added for good measure.
-/

section multiplicative_induction

/-- The principle of multiplicative induction for natural numbers -/
theorem nat_multiplicative_induction (P :   Prop) (h0 : P 0) (h1 : P 1) (hp :  (p : ), p.prime  P p)
  (hmult :  (m n : ), P m  P n  P (m*n)) (n : ) : P n :=
begin
  by_cases h : n = 0,
  { -- easy case `n = 0`
    rw h,
    exact h0, },
  -- now `n > 0`; take its factors
  let nf : multiset  := n.factors,
  have nfp : ( p  nf, nat.prime p) :=
  by { intro p, simp [nf], exact nat.prime_of_mem_factors, },
  have hp' : ( p  nf, P p) := by { intros p hyp, exact hp p (nfp p hyp), },
  have hn : nf.prod = n := by { simp [nf], exact nat.prod_factors h, },
  rw  hn,
  exact multiset.prod_induction P nf hmult h1 hp',
end

/-- The principle of multiplicative induction for natural numbers -/
theorem int_multiplicative_induction (P :   Prop) (h0 : P 0) (h1 : P 1) (hn1 : P (-1))
  (hp :  (p : ), p.prime  P p)
  (hmult :  (m n : ), P m  P n  P (m*n)) (n : ) : P n :=
begin
  -- reduce to the case of natural numbers
  let P' :   Prop := (λ n, P n),
  have hmult' : ( (m n : ), P' m  P' n  P' (m*n)) :=
  by { simp [P'], intros m n, exact hmult m n, },
  -- this gives us the statement for `|n|`
  have hP' := nat_multiplicative_induction P' (by assumption_mod_cast) (by assumption_mod_cast)
                (by assumption_mod_cast) hmult' n.nat_abs,
  simp [P'] at hP', -- gives `P ↑n.nat_abs`
  -- split according to sign
  cases int.nat_abs_eq n with hn hn,
  { -- `n = ↑n.nat_abs`
    rw [hn],
    exact hP' },
  { -- `n = -↑n.nat_abs`
    rw hn,
    rw (by ring : -(n.nat_abs : ) = (-1)*↑n.nat_abs),
    exact hmult (-1) n.nat_abs hn1 hP', },
end

end multiplicative_induction

Would it make sense to include that?

Johan Commelin (Mar 22 2022 at 09:42):

Yes, those look useful to me. Note that the second docstring should say integers instead of natural numbers

Ruben Van de Velde (Mar 22 2022 at 09:43):

lemma induction_on_primes {P :   Prop} (h₀ : P 0) (h₁ : P 1)
  (h :  p a : , p.prime  P a  P (p * a)) (n : ) : P n :=

Johan Commelin (Mar 22 2022 at 09:43):

Ooh, does that already exist?

Ruben Van de Velde (Mar 22 2022 at 09:44):

Yup: docs#induction_on_primes which is based on docs#unique_factorization_monoid.induction_on_prime

Ruben Van de Velde (Mar 22 2022 at 09:45):

Not sure why one is "prime" and the other "primes"

Michael Stoll (Mar 22 2022 at 09:47):

But note that my main assumption is different (multiplicative closure instead of closure under multiplication by a prime).

Michael Stoll (Mar 22 2022 at 09:52):

And I really needed the version for integers.

Ruben Van de Velde (Mar 22 2022 at 10:08):

The nat one is pretty similar:

theorem nat_multiplicative_induction (P :   Prop) (h0 : P 0) (h1 : P 1) (hp :  (p : ), p.prime  P p)
  (hmult :  (m n : ), P m  P n  P (m*n)) (n : ) : P n :=
induction_on_primes h0 h1 (λ p a pp ha, hmult _ _ (hp _ pp) ha) n

Michael Stoll (Mar 22 2022 at 10:12):

OK, that simplifies things a bit...

Damiano Testa (Mar 22 2022 at 10:17):

Michael, one thing that I have learned using mathlib, is that if I can prove a result in n lines, someone in this chat can prove it in 1.

Yaël Dillies (Mar 22 2022 at 10:18):

... by induction :rofl:

Damiano Testa (Mar 22 2022 at 10:18):

The library already contains a lot of results and someone will certainly know the exact one that is closest to the one you want and will be able to tell you.

Michael Stoll (Mar 22 2022 at 10:21):

Yeah, but it would really help to have a way of finding these oneself quickly!

Michael Stoll (Mar 22 2022 at 10:21):

(deleted)

Damiano Testa (Mar 22 2022 at 10:21):

This is what this chat is for!

Yaël Dillies (Mar 22 2022 at 10:21):

And the naming convention!

Damiano Testa (Mar 22 2022 at 10:21):

With time, you will be able to prove your results in n/2 lines...

Michael Stoll (Mar 22 2022 at 10:22):

I find that what is holding me up the most is
(1) getting Lean to prove the obvious
(2) figuring out where to find what I need in mathlib

Michael Stoll (Mar 22 2022 at 10:23):

Is there work under way addressing these issues?

Michael Stoll (Mar 22 2022 at 10:24):

Regarding (1), I would imagine some amount of (most likely AI-supported) heuristic proof search that goes more than one level deep.

Damiano Testa (Mar 22 2022 at 10:25):

When I was even more of a beginner than now, I found tidy very useful.

Ruben Van de Velde (Mar 22 2022 at 10:25):

int is perhaps worth adding, though:

theorem int_multiplicative_induction (P :   Prop) (h0 : P 0) (h1 : P 1) (hn1 : P (-1))
  (hp :  (p : ), p.prime  P p)
  (hmult :  (m n : ), P m  P n  P (m*n)) (n : ) : P n :=
begin
  have hp' :  p : , prime p  P p,
  { intros p pp,
    have : P p.nat_abs := hp _ (int.prime_iff_nat_abs_prime.mp pp),
    obtain hp'|hp' := int.nat_abs_eq p; rw hp',
    { exact this },
    { rw neg_one_mul,
      apply hmult _ _ hn1 this } },
  exact unique_factorization_monoid.induction_on_prime n h0
    (λ x hx, (int.is_unit_eq_one_or hx).elim (λ h, h.symm  h1) (λ h, h.symm  hn1))
    (λ a p haz pp hpa, hmult _ _ (hp' _ pp) hpa),
/- Or more painful:
  induction h : n.nat_abs using nat_multiplicative_induction with k ih generalizing n,
  { rwa int.eq_zero_of_nat_abs_eq_zero h, },
  { simp only [int.nat_abs_eq_iff, int.coe_nat_zero, int.coe_nat_succ, zero_add] at h,
    obtain rfl|rfl := h; assumption },
  { exact hp' n (int.prime_iff_nat_abs_prime.mpr (h.symm ▸ ih)), },
  { rw ←int.sign_mul_nat_abs n_1,
    apply hmult,
    { obtain hs|rfl|hs := lt_trichotomy 0 n_1,
      { rwa int.sign_eq_one_of_pos hs, },
      { rwa int.sign_zero },
      { rwa int.sign_eq_neg_one_of_neg hs } },
    { rw [h, int.coe_nat_mul],
      apply hmult,
      apply ᾰ,
      apply int.nat_abs_of_nat,
      apply ᾰ_1,
      apply int.nat_abs_of_nat } },
-/
end

Heather Macbeth (Mar 22 2022 at 10:26):

Michael Stoll said:

(2) figuring out where to find what I need in mathlib

Maybe it's Stockholm system, but all of us, even the "experts", have got very used to this human-based library search. It's so fast (and sociable) that it becomes less urgent to find automated alternatives.

Michael Stoll (Mar 22 2022 at 10:26):

I frequently try suggest, but I find it rarely to be helpful. Sometimes it comes up with exact ...and then I'm happy, but mostly I get a long list of useless stuff. E.g., when the goal is an equality, you get a list of results that can in principle prove an equality, but which are completely unrelated to the shape of the terms involved. (This could be related to the fact(?) that suggest sorts the results by length of lemma name, which tends to put unspecific ones first. Perhaps this could be changed so that the most specific ones appear on top?)

Yaël Dillies (Mar 22 2022 at 10:27):

There is suggest ... using ... which filters out the results to the ones that use the hypotheses you give in the second ...

Eric Wieser (Mar 22 2022 at 10:27):

Often I find that using Zulip is faster than waiting for library_search on my machine

Michael Stoll (Mar 22 2022 at 10:27):

@Ruben Van de Velde My proof was not that much longer (minus the comment lines) :smile:

Yaël Dillies (Mar 22 2022 at 10:28):

Nobody can know the full library, but you sure can know your own little folder by heart.

Michael Stoll (Mar 22 2022 at 10:29):

I find myself not remembering the names of lemmas that I used yesterday. Maybe this is just old age approaching...

Yaël Dillies (Mar 22 2022 at 10:29):

I can recite you everything that's under order., combinatorics., analysis.convex.. I have no idea what's under measure_theory. however.

Yaël Dillies (Mar 22 2022 at 10:31):

The idea is that you can then know about any bit of the library by asking the right person.

Eric Rodriguez (Mar 22 2022 at 10:31):

There's docs#nat.rec_on_prime_pow too, created as I was unaware (until today!) of the induction that Ruben mentioned

Eric Rodriguez (Mar 22 2022 at 10:32):

(there's some other spellings below that, too, which are helpful)

Yaël Dillies (Mar 22 2022 at 10:33):

I started a list of all recursors in the module docstring of file#data/nat/basic to avoid this precise situation. Please add yours!

Eric Rodriguez (Mar 22 2022 at 10:36):

Surely we should only put the ones in that file there? I'm happy to plop them there regardless :shrug:🏻‍♀️

Ruben Van de Velde (Mar 22 2022 at 10:36):

Michael Stoll said:

Ruben Van de Velde My proof was not that much longer (minus the comment lines) :smile:

Yeah, it wasn't as easy to derive from the general result as I'd hoped; it didn't really like the ∀ (p : ℕ), nat.prime p → P ↑p formulation. If that formulation is more useful for you, it's probably different enough to add to mathlib

Yaël Dillies (Mar 22 2022 at 10:39):

At the time I could only those in the file, but if there more just create a section gathering them all

Damiano Testa (Mar 22 2022 at 10:42):

Michael, in case it is helpful, I have used your proof of nat_multiplicative_induction and simply rewrote it in a more Lean-friendly way. I always find looking at the diffs in these proofs useful. Note, in particular, that I hold my breath and do not tell Lean on what to apply the lemmas, but wait for Lean to let me know what it wants. All the have and let have disappeared (and of course their content reappears when Lean wants it).

theorem nat_multiplicative_induction (P :   Prop) (h0 : P 0) (h1 : P 1) (hp :  (p : ), p.prime  P p)
  (hmult :  (m n : ), P m  P n  P (m*n)) (n : ) : P n :=
begin
  cases n,
  { -- easy case `n = 0`
    assumption },
  -- now `n > 0`; take its factors
  convert multiset.prod_induction P n.succ.factors hmult h1 _,
  { simpa only [multiset.coe_prod] using (nat.prod_factors (n.succ_ne_zero)).symm },
  { exact λ p hyp, hp p (nat.prime_of_mem_factors hyp) }
end

Michael Stoll (Mar 22 2022 at 10:42):

BTW, I just found docs#nat.rec_on_mul .

Michael Stoll (Mar 22 2022 at 10:44):

@Damiano Testa I guess it's a question whether one should try to write in a "Lean-friendly" or a "human-friendly" way. While developing a proof, I guess the latter makes more sense. For the former, you need experience to know what Lean prefers. Is there any documentation on this?

Damiano Testa (Mar 22 2022 at 10:46):

My approach is that if the statement has a proof that is "obvious", then I go for the quickest available proof that I can find. If the statement has some content, then I prefer a more discursive proof (better even if with comments, like you did).

Damiano Testa (Mar 22 2022 at 10:46):

I would categorize these induction statements as "obvious": once you know what to prove, you simply do it.

Michael Stoll (Mar 22 2022 at 10:47):

A search for "int.rec_on" doesn't seem to produce anything, though.

Kevin Buzzard (Mar 22 2022 at 18:36):

There's int.induction_on


Last updated: Dec 20 2023 at 11:08 UTC