Zulip Chat Archive

Stream: new members

Topic: Fibonacci Divisibility Sequence


Lawrence Lin (Feb 07 2023 at 03:50):

Hi, guys!! I just need to resolve some final steps in my Fibonacci code - can someone help with this?

def fib :  -> 
| 0 := 0
| 1 := 1
| (x+2) := fib (x) + fib (x+1)

lemma fib_rule (n : ) : fib(n + 2) = fib(n) + fib(n + 1) := rfl

theorem strong_induction {P :   Prop} {H :  n : , ( m : , m < n  P m)  P n} (n : ) : P n := sorry, -- this is already proven
theorem fib_add (m n : ) (hm : m > 0) (hn : n > 0): fib(m + n) = fib(n + 1) * fib(m) + fib(n) * fib(m - 1) := sorry, -- this is also proven

example (m n : ) (hm : m > 0) (hyp_div : m  n): fib(m)  fib(n) :=
begin
  rcases hyp_div with k, rfl⟩,
  induction k,
  {
    simp [fib],
  },
  {
    change fib m  fib(m * (k_n + 1)),
    rw [mul_add, add_comm, mul_one],
    rw fib_add (m) (m * k_n),
    apply dvd_add,
    simp,
    apply dvd_mul_of_dvd_left,
    apply k_ih,
    exact hm,
  },
end

now, all we have to do is say that since we're inducting on k and that this is the induction step, k must be greater than the base case (where k = 0). therefore, m and k are both positive -> their product is positive. how would i write this in LEAN?

Gareth Ma (Feb 07 2023 at 05:14):

@Lawrence Lin Sounds like something I would be good at by this point (I am new too) :P Firstly, the thing you are trying to prove right now is false, since your goal looks like

m: 
hm: m > 0
k_n: 
k_ih: fib m  fib (m * k_n)
 m * k_n > 0

Which is false for m = 1 and k_n = 0, since k | 0

Gareth Ma (Feb 07 2023 at 05:17):

I think you can treat the case n = 0 separately. Not sure if it's the best way but it's an easy way. So something like cases n at the start.

Gareth Ma (Feb 07 2023 at 05:20):

By the way here are some "I wish someone told me" for you
(1) almost always write <, since most theorems are written that way and it makes searching for theorems easier. So write 0 < m and such.
(2) you don't need a lot of the (), since lean interprets expressions after a function as its arguments. So fib m (m * k)would work instead of fib_add (m) (m * k_n)
(3) After you write simp you can change it to a squeeze_simp, then it will tell you which theorems it used. It will help you learn too!
(4) Also, I don't think you know this, but for induction you can name the arguments generated. The syntax is induction ... using ... .... In this case, you can write induction k with k ik, if you hate underscores like me

Gareth Ma (Feb 07 2023 at 05:30):

Oh and to answer your original question, you need mul_pos. Here:

example (m n : ) (hm : m > 0) (hyp_div : m  n): fib(m)  fib(n) :=
begin
  rcases hyp_div with k, rfl⟩,
  induction k,
  { simp [fib], },
  { by_cases h : k_n = 0,
    { rw [h, mul_one], },
    { replace h := nat.one_le_iff_ne_zero.2 h,
      change fib m  fib(m * (k_n + 1)),
      rw [mul_add, add_comm, mul_one],
      rw fib_add (m) (m * k_n),
      apply dvd_add,
      simp,
      apply dvd_mul_of_dvd_left,
      apply k_ih,
      exact hm,
      apply mul_pos hm h, }, },
end

Gareth Ma (Feb 07 2023 at 05:33):

example (m n : ) (hm : m > 0) (hyp_div : m  n): fib(m)  fib(n) :=
begin
  rcases hyp_div with k, rfl⟩,
  induction k,
  { simp [fib], },
  -- by the way, you can use `cases k_n` too, but then... you can try :)
  { by_cases h : k_n = 0,
    { rw [h, mul_one], },
    { replace h := nat.one_le_iff_ne_zero.2 h,
      -- rw [] writes each in order
      rw [nat.succ_eq_add_one, mul_add, add_comm, mul_one, fib_add m (m * k_n) hm _],
      apply dvd_add,
      apply dvd_mul_left,
      apply dvd_mul_of_dvd_left k_ih,
      apply mul_pos hm h, }, },
end

Lawrence Lin (Feb 07 2023 at 05:36):

thank you! let me digest this rq ;w;
also... i'm pretty sure lean was cool with the case fib(n) | 0? hm..

Gareth Ma (Feb 07 2023 at 05:38):

Yea lean is fine, that's exact what I prove in the { rw [h, mul_one] }. But to use mul_pos, it's not fine

Gareth Ma (Feb 07 2023 at 05:40):

Oh I think I know why. I think your (hn : n > 0) in fib_add is unnecessary.

Lawrence Lin (Feb 07 2023 at 05:40):

oh...

Lawrence Lin (Feb 07 2023 at 05:41):

yep, it was.

Lawrence Lin (Feb 07 2023 at 05:42):

i often find myself doing a lot of like, "nasty conversions" just to get lean to listen to me... sigh. i'll try to avoid it!! thank you for your help gareth c:

Gareth Ma (Feb 07 2023 at 05:42):

After removing that the proof is 7 lines (with the inlined brackets like I wrote it) :D

Gareth Ma (Feb 07 2023 at 05:42):

No problem!

Lawrence Lin (Feb 07 2023 at 05:42):

ooh 1s lemme try

Lawrence Lin (Feb 07 2023 at 05:43):

wait, the proof is 7 lines?

Gareth Ma (Feb 07 2023 at 05:43):

5 if I try

Gareth Ma (Feb 07 2023 at 05:43):

example (m n : ) (hm : m > 0) (hyp_div : m  n): fib(m)  fib(n) :=
begin
  rcases hyp_div with k, rfl⟩,
  induction k,
  { simp [fib], },
  { rw [nat.succ_eq_add_one, mul_add, add_comm, mul_one, fib_add m (m * k_n) hm],
    apply dvd_add,
    apply dvd_mul_left,
    apply dvd_mul_of_dvd_left k_ih, },
end

Lawrence Lin (Feb 07 2023 at 05:44):

oh...

Lawrence Lin (Feb 07 2023 at 05:44):

let me re-digest that :')

Gareth Ma (Feb 07 2023 at 05:47):

Here's one more thing you can try and explore. You see those repeated applys? It's annoying to type them out, especially when you have 9187359723859 different things. With simp, you can provide lemmas to it to tell lean which lemmas to use. So you can write this!

example (m n : ) (hm : m > 0) (hyp_div : m  n): fib(m)  fib(n) :=
begin
  rcases hyp_div with k, rfl⟩,
  induction k,
  { simp only [fib, mul_zero, dvd_zero], },
  { rw [nat.succ_eq_add_one, mul_add, add_comm, mul_one, fib_add m (m * k_n) hm],
    simp only [dvd_add, dvd_mul_left, dvd_mul_of_dvd_left k_ih], },
end

The only just means... "only". It speeds up computation too.

Lawrence Lin (Feb 07 2023 at 05:51):

oh wow.

Lawrence Lin (Feb 07 2023 at 05:52):

lemme try applying that to my old code

Lawrence Lin (Feb 07 2023 at 05:54):

seems like simp only doesn't really work sometimes

Lawrence Lin (Feb 07 2023 at 05:56):

specifically with lt_trans

Gareth Ma (Feb 07 2023 at 05:57):

Oh yea, essentially if uses it only if it knows everything it needs

Gareth Ma (Feb 07 2023 at 05:57):

For lt_trans you need two arguments lt_trans [[a < b]] [[b < c]], so you should provide those.

Lawrence Lin (Feb 07 2023 at 05:58):

fair enough
let me try

Lawrence Lin (Feb 07 2023 at 05:59):

ouch lean isn't happy with it, 1s

Lawrence Lin (Feb 07 2023 at 05:59):

simp only [lt_add_one, lt_trans [[lt_add_one]] [[lt_add_one]]],
did this

Lawrence Lin (Feb 07 2023 at 06:01):

theorem fib_add (m n : ) (hm : m > 0) : fib(m + n) = fib(n + 1) * fib(m) + fib(n) * fib(m - 1) :=
begin
  apply strong_induction n,
  intro k,
  intro h,
  cases k,
  { simp [fib] },
  {
    cases k,
    {
      simp [fib],
      simp only [fib_rule', hm],
    },
    {
      change fib(m + k) + fib(m + k + 1) = fib (k.succ.succ + 1) * fib m + fib k.succ.succ * fib (m - 1),
      rw [h, add_assoc m k 1, h (k+1), add_assoc],

      have H1 : fib (k + 1) * fib m + fib k * fib (m - 1) + fib (k + 1 + 1) * fib m + fib (k + 1) * fib (m - 1) = (fib (k + 1) + fib (k + 1 + 1)) * fib m + (fib(k) + fib(k + 1)) * fib (m - 1),
      {
        ring_nf,
      },

      rw H1,
      rw [fib_rule, fib_rule],

      simp only [lt_add_one],
      apply lt_trans,
      apply lt_add_one,
      apply lt_add_one,
    },
  },
end

here was the working lean code for fib_add

Lawrence Lin (Feb 07 2023 at 06:02):

(it is messy sorry)

Gareth Ma (Feb 07 2023 at 06:03):

Try exact lt_trans (lt_add_one _) (lt_add_one _) instead.

Lawrence Lin (Feb 07 2023 at 06:04):

why exact and not apply?

Gareth Ma (Feb 07 2023 at 06:05):

exact means (you guessed it) you have the exact statement

Gareth Ma (Feb 07 2023 at 06:05):

Here lt_trans ... is exactly what you want, so exact works

Lawrence Lin (Feb 07 2023 at 06:05):

ah

Lawrence Lin (Feb 07 2023 at 06:06):

do you know how i can get rid of my H1

Lawrence Lin (Feb 07 2023 at 06:06):

i think it's pretty unnecessary but...

Gareth Ma (Feb 07 2023 at 06:06):

By the way consider using by_cases like I did in my origin answer all the way up, it will decluster all the succ

Gareth Ma (Feb 07 2023 at 06:07):

Maybe I can try to prove that part from scratch, then you can see?

Lawrence Lin (Feb 07 2023 at 06:07):

ah- sure!

Lawrence Lin (Feb 07 2023 at 06:07):

thank you u.u

Lawrence Lin (Feb 07 2023 at 06:07):

(i don't know, been playing with lean for a few months and yet i still can't get the hang of it :( )

Lawrence Lin (Feb 07 2023 at 06:08):

i rmb implementing strong induction just to make that proof work haha

Gareth Ma (Feb 07 2023 at 06:13):

Hahaha, it's in mathlib already

Gareth Ma (Feb 07 2023 at 06:14):

https://leanprover-community.github.io/mathlib_docs/find/nat.strong_induction_on/
You use this by writing induction n using nat.strong_induction_on

Lawrence Lin (Feb 07 2023 at 06:17):

._.

Lawrence Lin (Feb 07 2023 at 06:17):

aaaaaaaaaa

Lawrence Lin (Feb 07 2023 at 06:17):

tbf i did try using that one then gave up ahaha ;w;
idk...

Gareth Ma (Feb 07 2023 at 06:37):

Sorry it took a while, I am slow too hahahaha. Here you go:

theorem fib_add (m n : ) (hm : 0 < m) : fib(m + n) = fib(n + 1) * fib(m) + fib(n) * fib(m - 1) :=
begin
  apply strong_induction n,
  -- use `intros` instead of `intro`
  intros k h,
  -- using by_cases instead of cases for... my eyes
  cases k,
  { simp [fib], },
  { cases k,
    { -- see how `fib_rule'` takes arguments, so i supply them? in `fib_rule' m hm`
      simp [fib, fib_rule' m hm],
    },
    { simp only [nat.succ_eq_add_one, add_assoc],
      norm_num,
      -- we "massage" things into the right form, then expand everything
      rw [ add_assoc, fib, nat.succ_eq_add_one, add_assoc m k 1],
      rw [h k _, h (k + 1) _],
      rw [fib_rule (k + 1), fib_rule k],
      -- and then ring gets rid of everything
      ring,
      exact nat.lt_succ_self _,
      exact lt_trans (nat.lt_succ_self _) (nat.lt_succ_self _),
    },
  },
end

Gareth Ma (Feb 07 2023 at 06:38):

but yea, my proof idea is "expand everything to base case, then deal with it", which seems to be yours too

Kevin Buzzard (Feb 07 2023 at 07:38):

You would be better off using r:=m-1 as your variable and not m, so you don't have to deal with natural subtraction and the hypothesis that m>0

Lawrence Lin (Feb 08 2023 at 02:32):

Gareth Ma said:

but yea, my proof idea is "expand everything to base case, then deal with it", which seems to be yours too

yep :3c


Last updated: Dec 20 2023 at 11:08 UTC