Zulip Chat Archive

Stream: new members

Topic: recursively defining binomial coefficients


Anand Rao (Jul 15 2021 at 08:05):

Hello, I am trying to define binomial coefficients on Z×Z\mathbb{Z} \times \mathbb{Z} in LEAN using Pascal's relation. I want to keep the original definition on N×N\mathbb{N} \times \mathbb{N} and set it to 00 everywhere else.
This is what I have done so far:

def binomial :     
  | _ 0 := 1
  | 0 _ := 0
  | (n+1) (k+1) := binomial n (k+1) + binomial n k

def extendedbinomial :     
  | (of_nat n) (of_nat k) := binomial n k
  | -[1+n] _ := 0
  | _ -[1+k] := 0

I am trying to condense this into a single definition, like this

def binomial :     
  | (int.of_nat n) (int.of_nat k) :=
    match n, k with
      | 0, 0 := 1
      | 0, _ := 0
      | (n+1), k := binomial n (k-1) + binomial n k
    end
  | _ _ := 0

but this gives issues since LEAN cannot prove that this recurrence is well-founded. I would not like to split this into the cases 0 and k.succ to make it well-founded, since that unnecessarily complicates proofs. Is there any other way of defining the Pascal identity on Z×Z\mathbb{Z} \times \mathbb{Z}?

Mario Carneiro (Jul 15 2021 at 08:15):

You need two definitions. This is easier in proofs in any case

Mario Carneiro (Jul 15 2021 at 08:16):

The other definition is basically naming that inner match statement in your combined definition, which will be extracted into an auxiliary anyway by lean

Kevin Buzzard (Jul 15 2021 at 08:17):

What about

open int

def extendedbinomial :     
  | (of_nat n) (of_nat 0) := 1
  | (of_nat 0) _          := 0
  | (of_nat (n+1)) (of_nat (k+1)) := extendedbinomial (of_nat n) (of_nat (k + 1)) + extendedbinomial (of_nat n) (of_nat k)
  | -[1+n] _ := 0
  | _ -[1+k] := 0

?

Mario Carneiro (Jul 15 2021 at 08:18):

I don't think that will work, for the same reason it does work

Mario Carneiro (Jul 15 2021 at 08:18):

It's not structural recursive (although maybe it is well founded by the default metric)

Anand Rao (Jul 15 2021 at 09:18):

Kevin Buzzard said:

What about

open int

def extendedbinomial :     
  | (of_nat n) (of_nat 0) := 1
  | (of_nat 0) _          := 0
  | (of_nat (n+1)) (of_nat (k+1)) := extendedbinomial (of_nat n) (of_nat (k + 1)) + extendedbinomial (of_nat n) (of_nat k)
  | -[1+n] _ := 0
  | _ -[1+k] := 0

?

Thank you, this seems to wrap both definitions into a common one.
I was also looking for a way to get the Pascal recurrence to apply to expressions of the form binomial n 0 (where n is an arbitrary natural number), instead of defining expressions of this form to be equal to 1. This makes proofs easier, since one doesn't have to distinguish between the k = 0 case and the k.succ case.

Anand Rao (Jul 15 2021 at 09:20):

Mario Carneiro said:

The other definition is basically naming that inner match statement in your combined definition, which will be extracted into an auxiliary anyway by lean

Actually with the inner match, I was trying to define the Pascal recurrence more generally so it applies to the k = 0 case as well.

Anand Rao (Jul 15 2021 at 09:39):

I tried the following definition as well with nbinomial n k = binomial (n-1) (k-1), but it didn't work

def nbinomial :     
  | 0 _ := 0
  | n 0 := 0
  | 1 1 := 1
  | 1 _ := 0
  | _ 1 := 1
  | (n+2) (k+2) := nbinomial (n+1) (k+1) + nbinomial (n+1) (k+2)

Mario Carneiro (Jul 15 2021 at 13:04):

Anand Rao said:

I was also looking for a way to get the Pascal recurrence to apply to expressions of the form binomial n 0 (where n is an arbitrary natural number), instead of defining expressions of this form to be equal to 1. This makes proofs easier, since one doesn't have to distinguish between the k = 0 case and the k.succ case.

In that case, it would be more natural to not extend n to int and only do that for k. The recurrence is quite straightforward and structural recursive:

open int

def binomial :     
| 0 0 := 1
| 0 _ := 0
| (n+1) k := binomial n (k-1) + binomial n k

Last updated: Dec 20 2023 at 11:08 UTC