ComboCombinatorics
Require Export Sort.
Learning to count all over again
Sums and products: simple counting
Suppose there [n] ways to do something, and there are another [m] ways to do it differently, then there are [n + m] ways to do it.
For the train, we'll just use arbitrary other numbers to represent the options.
Altogether, we can model the choice of driving or taking the train
using list append, ++.
In fact, youv'e already proved a general theorem validating the
sum rule. It's called app_length, and you proved it way back in
Poly.v!
- Question: suppose there are three different kinds of tacos
(vegetarian, carnitas, al pastor) and two different kinds of
enchilada (cheese, chicken). How many different dishes are there?
Inductive pasta :=
| spaghetti : pasta
| tagliatelle : pasta
| fettuccine : pasta
| fusilli : pasta
| penne : pasta.
| spaghetti : pasta
| tagliatelle : pasta
| fettuccine : pasta
| fusilli : pasta
| penne : pasta.
Here's the listing on your menu:
Definition pastas : list pasta := [spaghetti; tagliatelle; fettuccine; fusilli; penne].
Inductive topping :=
| none : topping
| vegetables : topping
| meatballs : topping
| seafood : topping.
Definition toppings : list topping := [none; vegetables; meatballs; seafood].
Inductive sauce :=
| aglio_e_olio : sauce (* olive oil and garlic---simple but delicious! *)
| marinara : sauce (* tomato sauce with herbs, garlic, and onions *)
| alfredo : sauce. (* traditionally just butter and parmagianno reggiano,
but often with a hint of cream, too *)
Definition sauces : list sauce := [aglio_e_olio; marinara; alfredo].
Inductive topping :=
| none : topping
| vegetables : topping
| meatballs : topping
| seafood : topping.
Definition toppings : list topping := [none; vegetables; meatballs; seafood].
Inductive sauce :=
| aglio_e_olio : sauce (* olive oil and garlic---simple but delicious! *)
| marinara : sauce (* tomato sauce with herbs, garlic, and onions *)
| alfredo : sauce. (* traditionally just butter and parmagianno reggiano,
but often with a hint of cream, too *)
Definition sauces : list sauce := [aglio_e_olio; marinara; alfredo].
Given our menu of pastas, toppings, and sauces, we might
want to know how many different dishes you can make.
To start, how many different topping/sauce combinations are there?
To enumerate them manually, it helps to be methodical: for each
possible topping, consider the sauces it could go with:
Totting it all up, there are twelve options. You might have
noticed that there are 4 toppings and 3 sauces, and 12 = 4 * 3.
It's no coincidence! We can apply what is called the product rule:
- none with aglio_e_olio
- none with marinara
- none with alfredo
- vegetables with aglio_e_olio
- vegetables with marinara
- vegetables with alfredo
- meatballs with aglio_e_olio
- meatballs with marinara
- meatballs with alfredo
- seafood with aglio_e_olio
- seafood with marinara
- seafood with alfredo
Suppose you are performing two-part task. If there are n ways to do the first part and m ways to do the second part, there n*m ways to do the whole task.
Exercise: 1 star (product_exercises)
How many different pasta combinations does your pasta restaurant offer? Write down the calculation that lead to your answer.
(* FILL IN HERE *)
A TLA is a three-letter acronym, like NSF, TLA, ALA, or
AAA. How many TLAs are there using the English alphabet? Write
down the calculation that lead to your answer.
(* FILL IN HERE *)
How many TLAs are there in English with no repeated characters?
For example, TLA would be allowed but ALA would not—and AAA is
right out. Give a calculation that explains your answer.
(* FILL IN HERE *)
☐
Exercise: 2 stars (tlas_more)
How many TLAs are there in English with no more than one repeated character? TLA and ALA are fine, but AAA is disallowed. Explain your reasoning in detail and give a calculation that explains your answer.
(* FILL IN HERE *)
Compare your answers for the second part of product_exercises
and the first part of tlas_more. Can you explain how the two
answers relate? Give another calculation to explain your answer to
Problem (1c).
(* FILL IN HERE *)
☐
Exercise: 2 stars (product_times)
Formalize the product rule in Coq.
Fixpoint product {X Y:Type} (l1 : list X) (l2 : list Y) : list (X * Y)
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Example product_example1 :
length (product toppings sauces) = 12.
Proof. (* FILL IN HERE *) Admitted.
Example product_example2 :
length (product [1;2;3] [true;false]) = 6.
Proof. (* FILL IN HERE *) Admitted.
Lemma product_times : ∀ X Y (l1 : list X) (l2 : list Y),
length (product l1 l2) = length l1 * length l2.
Proof.
(* FILL IN HERE *) Admitted.
☐
(* REPLACE THIS LINE WITH ":= _your_definition_ ." *). Admitted.
Example product_example1 :
length (product toppings sauces) = 12.
Proof. (* FILL IN HERE *) Admitted.
Example product_example2 :
length (product [1;2;3] [true;false]) = 6.
Proof. (* FILL IN HERE *) Admitted.
Lemma product_times : ∀ X Y (l1 : list X) (l2 : list Y),
length (product l1 l2) = length l1 * length l2.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 3 stars (lists_of_bools)
How many lists of booleans of length 2 are there? Write them out.
(* FILL IN HERE *)
How many lists of booleans of length 3 are there? No need to write
them out.
(* FILL IN HERE *)
Write a theorem characterizing how many many lists of booleans of
length n are there, for any natural n. Your proof should be
informal.
(* FILL IN HERE *)
☐
Order in the court: factorial and permutations
Exercise: 2 stars (perms_two_of_six)
How many ways are there to pick two elements from the list 1;2;3;4;5;6? Hint: use the product rule.
(* FILL IN HERE *)
☐
- aglio_e_olio, marinara, alfredo
- aglio_e_olio, alfredo, marinara
- alfredo, aglio_e_olio, marinara
- alfredo, marinara, aglio_e_olio
- marinara, alfredo, aglio_e_olio
- marinara, aglio_e_olio, alfredo
- There are three ways to choose the first sauce—-it could be any
of them.
- Once we've chosen the first suace, there's only two possible
chocies for the next sauce.
- Finally, after we've picked the first two sauces, there's only one choice for the third sauce.
Fixpoint factorial (n:nat) : nat :=
match n with
| 0 ⇒ 1
| S n' ⇒ n * factorial n'
end.
Example fact_0__1 : factorial 0 = 1.
Proof. reflexivity. Qed.
Example fact_5__120 : factorial 5 = 120.
Proof. reflexivity. Qed.
match n with
| 0 ⇒ 1
| S n' ⇒ n * factorial n'
end.
Example fact_0__1 : factorial 0 = 1.
Proof. reflexivity. Qed.
Example fact_5__120 : factorial 5 = 120.
Proof. reflexivity. Qed.
One might ask why factorial 0 = 1. To phrase it another way: how
many different orderings are there of the empty list? Just one!
We can in fact able to say more than that: for all n, factorial
n is nonzero.
☐
Exercise: 1 star (factorial_nz)
Exercise: 1 star (perms_six)
How many permutations are there of the list 1;2;3;4;5;6? You don't need to write them all out—-in fact, please don't!
(* FILL IN HERE *)
☐
Relating factorial to permutations
Fixpoint everywhere {A:Type} (a:A) (ls:list A) : list (list A) :=
match ls with
| [] ⇒ [[a]] | h :: t ⇒ (a :: ls) :: (map (fun t' ⇒ h::t') (everywhere a t))
end.
Example everywhere_1_234 :
everywhere 1 [2;3;4] = [[1;2;3;4];
[2;1;3;4];
[2;3;1;4];
[2;3;4;1]].
Proof. reflexivity. Qed.
match ls with
| [] ⇒ [[a]] | h :: t ⇒ (a :: ls) :: (map (fun t' ⇒ h::t') (everywhere a t))
end.
Example everywhere_1_234 :
everywhere 1 [2;3;4] = [[1;2;3;4];
[2;1;3;4];
[2;3;1;4];
[2;3;4;1]].
Proof. reflexivity. Qed.
Suppose we have a list h::t. Given an element h and a list
permutatons ls of the tail t, how might we collect all
possible insertions of h? The function concat_map will serve:
Fixpoint concat_map {A B:Type} (f:A → list B) (l:list A) : list B :=
match l with
| [] ⇒ []
| a :: l' ⇒ f a ++ concat_map f l'
end.
Fixpoint permutations {A:Type} (ls:list A) : list (list A) :=
match ls with
| [] ⇒ [[]] | h :: t ⇒ concat_map (everywhere h) (permutations t)
end.
Compute (permutations [1;2;3;4]).
Example permutations_1234 :
permutations [1;2;3;4] =
[(* insert 1 everywhere into 2;3;4 *)
[1; 2; 3; 4];
[2; 1; 3; 4];
[2; 3; 1; 4];
[2; 3; 4; 1];
(* insert 1 everywhere into 3;2;4 *)
[1; 3; 2; 4];
[3; 1; 2; 4];
[3; 2; 1; 4];
[3; 2; 4; 1];
(* insert 1 everywhere into 3;4;2 *)
[1; 3; 4; 2];
[3; 1; 4; 2];
[3; 4; 1; 2];
[3; 4; 2; 1];
(* insert 1 everywhere into 2;4;3 *)
[1; 2; 4; 3];
[2; 1; 4; 3];
[2; 4; 1; 3];
[2; 4; 3; 1];
(* insert 1 everywhere into 4;2;3 *)
[1; 4; 2; 3];
[4; 1; 2; 3];
[4; 2; 1; 3];
[4; 2; 3; 1];
(* insert 1 everywhere into 4;3;2 *)
[1; 4; 3; 2];
[4; 1; 3; 2];
[4; 3; 1; 2];
[4; 3; 2; 1]].
Proof. reflexivity. Qed.
Compute length (everywhere 5 [1;2;3;4]).
match l with
| [] ⇒ []
| a :: l' ⇒ f a ++ concat_map f l'
end.
Fixpoint permutations {A:Type} (ls:list A) : list (list A) :=
match ls with
| [] ⇒ [[]] | h :: t ⇒ concat_map (everywhere h) (permutations t)
end.
Compute (permutations [1;2;3;4]).
Example permutations_1234 :
permutations [1;2;3;4] =
[(* insert 1 everywhere into 2;3;4 *)
[1; 2; 3; 4];
[2; 1; 3; 4];
[2; 3; 1; 4];
[2; 3; 4; 1];
(* insert 1 everywhere into 3;2;4 *)
[1; 3; 2; 4];
[3; 1; 2; 4];
[3; 2; 1; 4];
[3; 2; 4; 1];
(* insert 1 everywhere into 3;4;2 *)
[1; 3; 4; 2];
[3; 1; 4; 2];
[3; 4; 1; 2];
[3; 4; 2; 1];
(* insert 1 everywhere into 2;4;3 *)
[1; 2; 4; 3];
[2; 1; 4; 3];
[2; 4; 1; 3];
[2; 4; 3; 1];
(* insert 1 everywhere into 4;2;3 *)
[1; 4; 2; 3];
[4; 1; 2; 3];
[4; 2; 1; 3];
[4; 2; 3; 1];
(* insert 1 everywhere into 4;3;2 *)
[1; 4; 3; 2];
[4; 1; 3; 2];
[4; 3; 1; 2];
[4; 3; 2; 1]].
Proof. reflexivity. Qed.
Compute length (everywhere 5 [1;2;3;4]).
What does our function permutations have to do with the
inductive proposition Permutation? We can prove that our
function permutations is in some sense complete: everything it
produces is a permutation of the given list.
Exercise: 2 stars, optional (permutations_complete_aux)
Lemma In_concat_map:
∀ (A B : Type) (f : A → list B) (l : list A) (y : B),
In y (concat_map f l) → (∃ x : A, In y (f x) ∧ In x l).
Proof.
(* FILL IN HERE *) Admitted.
Lemma everywhere_perm : ∀ A (l l' : list A) (x : A),
In l' (everywhere x l) →
Permutation (x :: l) l'.
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ (A B : Type) (f : A → list B) (l : list A) (y : B),
In y (concat_map f l) → (∃ x : A, In y (f x) ∧ In x l).
Proof.
(* FILL IN HERE *) Admitted.
Lemma everywhere_perm : ∀ A (l l' : list A) (x : A),
In l' (everywhere x l) →
Permutation (x :: l) l'.
Proof.
(* FILL IN HERE *) Admitted.
Theorem permutations_complete : ∀ A (l l' : list A),
In l' (permutations l) → Permutation l l'.
Proof.
(* FILL IN HERE *) Admitted.
☐
In l' (permutations l) → Permutation l l'.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 5 stars, advanced, optional (permutations_correct)
It's possible to prove the converse, that Permutation l l' implies In l' (permutations l). Feel free to give it a go, but it's very challenging! ☐Exercise: 2 stars, optional (permutation_length_aux)
Lemma In_everywhere_length :
∀ A (a:A) (l perm:list A),
In perm (everywhere a l) →
length perm = S (length l).
Proof.
(* FILL IN HERE *) Admitted.
Lemma length_concat_map :
∀ A B (f:A → list B) (l:list A) n,
(∀ y, In y l → length (f y) = n) →
length (concat_map f l) = n * length l.
Proof.
(* FILL IN HERE *) Admitted.
Lemma length_permutation :
∀ A n (l:list A),
length l = n →
∀ y, In y (permutations l) → length y = n.
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ A (a:A) (l perm:list A),
In perm (everywhere a l) →
length perm = S (length l).
Proof.
(* FILL IN HERE *) Admitted.
Lemma length_concat_map :
∀ A B (f:A → list B) (l:list A) n,
(∀ y, In y l → length (f y) = n) →
length (concat_map f l) = n * length l.
Proof.
(* FILL IN HERE *) Admitted.
Lemma length_permutation :
∀ A n (l:list A),
length l = n →
∀ y, In y (permutations l) → length y = n.
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 3 stars (permutation_length)
You may need to define and prove an auxiliary lemma in order to see how everywhere and length interact.
Lemma permutation_length :
∀ A (l l':list A) (a:A),
In l' (permutations l) → length (everywhere a l') = S (length l).
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ A (l l':list A) (a:A),
In l' (permutations l) → length (everywhere a l') = S (length l).
Proof.
(* FILL IN HERE *) Admitted.
Exercise: 2 stars (permutations_length)
We can finally prove the desired result: there are factorial n permutations of a list of length n.
Lemma permutations_length :
∀ A (l:list A) n,
length l = n →
length (permutations l) = factorial n.
Proof.
(* FILL IN HERE *) Admitted.
☐
∀ A (l:list A) n,
length l = n →
length (permutations l) = factorial n.
Proof.
(* FILL IN HERE *) Admitted.
The division rule
- [1;2]
- [1;3]
- [1;4]
- [2;1]
- [2;3]
- [2;4]
- [3;1]
- [3;2]
- [3;4]
- [4;1]
- [4;2]
- [4;3]
- [1;2]
- [1;3]
- [1;4]
- [2;3]
- [2;4]
- [3;4]
Exercise: 2 stars (choose_two_of_six)
How many ways are there to pick two elements from the list [1;2;3;4;5;6] if you don't care about order?
(* FILL IN HERE *)
☐
Fixpoint choose (n m : nat) : nat :=
match n, m with
| _, O ⇒ 1
| O, S m' ⇒ 0
| S n', S m' ⇒ choose n' (S m') + choose n' m'
end.
Example choose_two_of_six : choose 6 2 = 15.
Proof. reflexivity. Qed.
We can characterize choose in terms of a few useful equations.
Lemma choose_n_0 : ∀ n : nat, choose n 0 = 1.
Proof.
(* FILL IN HERE *) Admitted.
Lemma choose_n_lt_m : ∀ n m : nat,
n < m → choose n m = 0.
Proof.
(* FILL IN HERE *) Admitted.
Lemma choose_n_n : ∀ n : nat, choose n n = 1.
Proof.
(* FILL IN HERE *) Admitted.
Proof.
(* FILL IN HERE *) Admitted.
Lemma choose_n_lt_m : ∀ n m : nat,
n < m → choose n m = 0.
Proof.
(* FILL IN HERE *) Admitted.
Lemma choose_n_n : ∀ n : nat, choose n n = 1.
Proof.
(* FILL IN HERE *) Admitted.
We built the following into our definition, but in fact it's
Pascal's Identity, named after Blaise Pascal.
Lemma choose_pascal : ∀ n k : nat,
choose (S n) (S k) = choose n (S k) + choose n k.
Proof.
simpl. reflexivity.
Qed.
choose (S n) (S k) = choose n (S k) + choose n k.
Proof.
simpl. reflexivity.
Qed.
Exercise: 2 stars (taco_tuesday)
A taco stand sells four kinds of tacos: al pastor, carne asada, campechanos, and jalape\~nos rellenos.- Suppose you order one each of all four tacos. Assuming you finish each taco before starting on the next one, how many different orders could you eat your tacos in?
(* FILL IN HERE *)
- How many different plates of three tacos are there? You can order more than one of a given kind, i.e., there can be duplicates, and you'll eat the plate from left to right (so order matters).
(* FILL IN HERE *)
- Variety is the spice of life. Suppose you don't get more than one of any given kind of taco. How many different plates of three \textit{distinct} tacos are there, if order doesn't matter?
(* FILL IN HERE *)
☐
Defining choose in terms of factorial
Lemma choose_fact : ∀ m n : nat,
choose (n + m) n * (factorial n * factorial m) = factorial (n + m).
Proof.
intros m. induction m as [|m' IHm']; intros n; simpl.
- rewrite <- plus_n_O. rewrite choose_n_n.
simpl. rewrite <- plus_n_O. rewrite mult_comm. apply mult_1_l.
- induction n as [|n' IHn'].
+ simpl. rewrite <- plus_n_O. rewrite <- plus_n_O. reflexivity.
+ assert (S n' + S m' = S (S n' + m')) as HeqSS.
{ simpl. rewrite <- plus_n_Sm. reflexivity. }
rewrite HeqSS. clear HeqSS.
rewrite choose_pascal. rewrite mult_plus_distr_r.
apply eq_trans with (y := factorial (S n' + m') * S m' + factorial (n' + S m') * S n').
apply f_equal2.
{ rewrite <- IHm'.
rewrite <- mult_assoc.
rewrite <- mult_assoc.
rewrite (mult_comm (factorial m')).
reflexivity. }
{ rewrite <- IHn'.
rewrite <- plus_n_Sm.
rewrite <- mult_assoc.
rewrite <- mult_assoc.
rewrite <- (mult_comm (S n')).
rewrite (mult_assoc (factorial n')).
rewrite <- (mult_comm (S n')).
reflexivity. }
apply eq_trans with (y := (S m' + S n') * factorial (S n' + m')).
rewrite mult_plus_distr_r. apply f_equal2.
{ apply mult_comm. }
{ rewrite mult_comm.
rewrite <- plus_n_Sm.
reflexivity. }
unfold factorial. fold factorial.
rewrite plus_n_Sm. rewrite plus_comm.
reflexivity.
Qed.
choose (n + m) n * (factorial n * factorial m) = factorial (n + m).
Proof.
intros m. induction m as [|m' IHm']; intros n; simpl.
- rewrite <- plus_n_O. rewrite choose_n_n.
simpl. rewrite <- plus_n_O. rewrite mult_comm. apply mult_1_l.
- induction n as [|n' IHn'].
+ simpl. rewrite <- plus_n_O. rewrite <- plus_n_O. reflexivity.
+ assert (S n' + S m' = S (S n' + m')) as HeqSS.
{ simpl. rewrite <- plus_n_Sm. reflexivity. }
rewrite HeqSS. clear HeqSS.
rewrite choose_pascal. rewrite mult_plus_distr_r.
apply eq_trans with (y := factorial (S n' + m') * S m' + factorial (n' + S m') * S n').
apply f_equal2.
{ rewrite <- IHm'.
rewrite <- mult_assoc.
rewrite <- mult_assoc.
rewrite (mult_comm (factorial m')).
reflexivity. }
{ rewrite <- IHn'.
rewrite <- plus_n_Sm.
rewrite <- mult_assoc.
rewrite <- mult_assoc.
rewrite <- (mult_comm (S n')).
rewrite (mult_assoc (factorial n')).
rewrite <- (mult_comm (S n')).
reflexivity. }
apply eq_trans with (y := (S m' + S n') * factorial (S n' + m')).
rewrite mult_plus_distr_r. apply f_equal2.
{ apply mult_comm. }
{ rewrite mult_comm.
rewrite <- plus_n_Sm.
reflexivity. }
unfold factorial. fold factorial.
rewrite plus_n_Sm. rewrite plus_comm.
reflexivity.
Qed.
Exercise: 4 stars (choose_fact_informal)
Using the Coq proof above, prove that
choose (n + m) n * (factorial n * factorial m) = factorial (n + m).
for all n and m.
(* FILL IN HERE *)
☐
Other identities for choice
choose n m = choose n (n - m)
choose (n+m) m = choose (n+m) n
Exercise: 3 stars (mult_nz)
Lemma mult_nz : ∀ m n nz : nat,
m * nz = n * nz →
nz ≠ 0 →
m = n.
Proof.
(* FILL IN HERE *) Admitted.
☐
m * nz = n * nz →
nz ≠ 0 →
m = n.
Proof.
(* FILL IN HERE *) Admitted.
Lemma choose_swap : ∀ m n : nat,
choose (n + m) m = choose (n + m) n.
Proof.
(* FILL IN HERE *) Admitted.
☐
choose (n + m) m = choose (n + m) n.
Proof.
(* FILL IN HERE *) Admitted.
The binomial theorem
exp (x + y) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
(* sum_nm n m (fun i => e) == sum_i=m^n e *)
Fixpoint sum_nm (n m : nat) (f : nat → nat) : nat :=
match n with
| O ⇒ f m
| S n' ⇒ f m + sum_nm n' (S m) f
end.
Lemma sum_nm_i : ∀ (m n : nat) (f : nat → nat),
sum_nm (S n) m f = f m + sum_nm n (S m) f.
Proof.
intros.
simpl.
reflexivity.
Qed.
Fixpoint sum_nm (n m : nat) (f : nat → nat) : nat :=
match n with
| O ⇒ f m
| S n' ⇒ f m + sum_nm n' (S m) f
end.
Lemma sum_nm_i : ∀ (m n : nat) (f : nat → nat),
sum_nm (S n) m f = f m + sum_nm n (S m) f.
Proof.
intros.
simpl.
reflexivity.
Qed.
Exercise: 2 stars, optional (sum_identities)
The following make good practice and will familiarize you with sum_nm. That said, we won't use sum_nm again in the course.
Lemma sum_nm_f : ∀ (m n : nat) (f : nat → nat),
sum_nm (S n) m f = sum_nm n m f + f (m + S n).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_ext : ∀ (m n : nat) (f g : nat → nat),
(∀ x : nat, x ≤ n → f (m + x) = g (m + x)) →
sum_nm n m f = sum_nm n m g.
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_add : ∀ (m n : nat) (f g : nat → nat),
sum_nm n m f + sum_nm n m g = sum_nm n m (fun i : nat ⇒ f i + g i).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_times : ∀ (m n x : nat) (f : nat → nat),
x * sum_nm n m f = sum_nm n m (fun i : nat ⇒ x * f i).
Proof.
(* FILL IN HERE *) Admitted.
Lemma t_sum_Svars : ∀ (m n : nat) (f : nat → nat),
sum_nm n m f = sum_nm n (S m) (fun i : nat ⇒ f (pred i)).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_zeroton : ∀ n : nat,
2 * sum_nm n 0 (fun i : nat ⇒ i) = n * (n + 1).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_odds : ∀ n : nat,
sum_nm n 0 (fun i : nat ⇒ S (2*i)) = (S n) * (S n).
Proof.
(* FILL IN HERE *) Admitted.
☐
sum_nm (S n) m f = sum_nm n m f + f (m + S n).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_ext : ∀ (m n : nat) (f g : nat → nat),
(∀ x : nat, x ≤ n → f (m + x) = g (m + x)) →
sum_nm n m f = sum_nm n m g.
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_add : ∀ (m n : nat) (f g : nat → nat),
sum_nm n m f + sum_nm n m g = sum_nm n m (fun i : nat ⇒ f i + g i).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_nm_times : ∀ (m n x : nat) (f : nat → nat),
x * sum_nm n m f = sum_nm n m (fun i : nat ⇒ x * f i).
Proof.
(* FILL IN HERE *) Admitted.
Lemma t_sum_Svars : ∀ (m n : nat) (f : nat → nat),
sum_nm n m f = sum_nm n (S m) (fun i : nat ⇒ f (pred i)).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_zeroton : ∀ n : nat,
2 * sum_nm n 0 (fun i : nat ⇒ i) = n * (n + 1).
Proof.
(* FILL IN HERE *) Admitted.
Lemma sum_odds : ∀ n : nat,
sum_nm n 0 (fun i : nat ⇒ S (2*i)) = (S n) * (S n).
Proof.
(* FILL IN HERE *) Admitted.
Lemma minus_Sn_m: ∀ n m : nat,
m ≤ n → S (n - m) = S n - m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem binomial: ∀ x y n : nat,
exp (x + y) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
Proof.
intros x y n. induction n as [|n' IHn'].
- simpl. reflexivity.
- destruct n' as [|n'].
+ simpl.
repeat rewrite (mult_comm _ 1).
repeat rewrite mult_1_l.
repeat rewrite <- plus_n_O. reflexivity.
+ replace (exp (x + y) (S (S n'))) with ((x + y) * (exp (x + y) (S n'))) by reflexivity.
rewrite IHn'. rewrite mult_plus_distr_r.
rewrite sum_nm_times. rewrite sum_nm_times.
rewrite sum_nm_i. rewrite choose_n_0.
replace (exp y 0) with 1 by reflexivity.
rewrite mult_1_l. rewrite (mult_comm _ 1). rewrite mult_1_l. rewrite <- minus_n_O.
rewrite sum_nm_f. rewrite choose_n_n.
rewrite plus_O_n. rewrite minus_diag. replace (exp x 0) with 1 by reflexivity.
repeat rewrite mult_1_l.
rewrite (t_sum_Svars 0 n').
replace
(x * exp x (S n') +
sum_nm n' 1
(fun i : nat ⇒
x * (choose (S n') i * (exp x (S n' - i) * exp y i))) +
(sum_nm n' 1
(fun i : nat ⇒
y *
(choose (S n') (pred i) *
(exp x (S n' - pred i) * exp y (pred i)))) +
y * exp y (S n'))) with
(exp x (S (S n')) +
(sum_nm n' 1
(fun i : nat ⇒
choose (S (S n')) i * (exp x (S (S n') - i) * exp y i)) +
exp y (S (S n')))).
rewrite (sum_nm_i 0). rewrite (sum_nm_f 1).
rewrite choose_n_0. rewrite choose_n_n.
rewrite <- minus_n_O.
rewrite minus_diag.
replace (exp x 0) with 1 by reflexivity.
replace (exp y 0) with 1 by reflexivity.
rewrite (mult_comm _ 1). repeat rewrite mult_1_l.
replace (1 + S n') with (S (S n')) by reflexivity.
reflexivity. (* !!! *)
(* old proof obligation from replace *)
{ replace (x * exp x (S n')) with (exp x (S (S n'))) by reflexivity.
replace (y * exp y (S n')) with (exp y (S (S n'))) by reflexivity.
repeat rewrite <- plus_assoc.
apply f_equal2. reflexivity.
rewrite plus_assoc.
apply f_equal2.
- rewrite sum_nm_add.
apply sum_nm_ext.
intros i Hi.
replace (pred (1 + i)) with i by reflexivity.
replace (1 + i) with (S i) by reflexivity.
replace (S (S n') - S i) with (S n' - i) by reflexivity.
replace (S n' - S i) with (n' - i) by reflexivity.
rewrite (choose_pascal (S n')).
rewrite mult_plus_distr_r.
apply f_equal2.
* rewrite (mult_comm x). rewrite <- mult_assoc. apply f_equal2.
{ reflexivity. }
{ rewrite <- mult_assoc. rewrite (mult_comm _ x).
rewrite mult_assoc. apply f_equal2.
rewrite <- minus_Sn_m. rewrite mult_comm. reflexivity. apply Hi.
reflexivity. }
* rewrite (mult_comm y). rewrite <- mult_assoc. apply f_equal2.
{ reflexivity. }
{ rewrite <- mult_assoc. apply f_equal2. reflexivity.
rewrite mult_comm. reflexivity. }
- reflexivity.
}
Qed.
m ≤ n → S (n - m) = S n - m.
Proof.
(* FILL IN HERE *) Admitted.
Theorem binomial: ∀ x y n : nat,
exp (x + y) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
Proof.
intros x y n. induction n as [|n' IHn'].
- simpl. reflexivity.
- destruct n' as [|n'].
+ simpl.
repeat rewrite (mult_comm _ 1).
repeat rewrite mult_1_l.
repeat rewrite <- plus_n_O. reflexivity.
+ replace (exp (x + y) (S (S n'))) with ((x + y) * (exp (x + y) (S n'))) by reflexivity.
rewrite IHn'. rewrite mult_plus_distr_r.
rewrite sum_nm_times. rewrite sum_nm_times.
rewrite sum_nm_i. rewrite choose_n_0.
replace (exp y 0) with 1 by reflexivity.
rewrite mult_1_l. rewrite (mult_comm _ 1). rewrite mult_1_l. rewrite <- minus_n_O.
rewrite sum_nm_f. rewrite choose_n_n.
rewrite plus_O_n. rewrite minus_diag. replace (exp x 0) with 1 by reflexivity.
repeat rewrite mult_1_l.
rewrite (t_sum_Svars 0 n').
replace
(x * exp x (S n') +
sum_nm n' 1
(fun i : nat ⇒
x * (choose (S n') i * (exp x (S n' - i) * exp y i))) +
(sum_nm n' 1
(fun i : nat ⇒
y *
(choose (S n') (pred i) *
(exp x (S n' - pred i) * exp y (pred i)))) +
y * exp y (S n'))) with
(exp x (S (S n')) +
(sum_nm n' 1
(fun i : nat ⇒
choose (S (S n')) i * (exp x (S (S n') - i) * exp y i)) +
exp y (S (S n')))).
rewrite (sum_nm_i 0). rewrite (sum_nm_f 1).
rewrite choose_n_0. rewrite choose_n_n.
rewrite <- minus_n_O.
rewrite minus_diag.
replace (exp x 0) with 1 by reflexivity.
replace (exp y 0) with 1 by reflexivity.
rewrite (mult_comm _ 1). repeat rewrite mult_1_l.
replace (1 + S n') with (S (S n')) by reflexivity.
reflexivity. (* !!! *)
(* old proof obligation from replace *)
{ replace (x * exp x (S n')) with (exp x (S (S n'))) by reflexivity.
replace (y * exp y (S n')) with (exp y (S (S n'))) by reflexivity.
repeat rewrite <- plus_assoc.
apply f_equal2. reflexivity.
rewrite plus_assoc.
apply f_equal2.
- rewrite sum_nm_add.
apply sum_nm_ext.
intros i Hi.
replace (pred (1 + i)) with i by reflexivity.
replace (1 + i) with (S i) by reflexivity.
replace (S (S n') - S i) with (S n' - i) by reflexivity.
replace (S n' - S i) with (n' - i) by reflexivity.
rewrite (choose_pascal (S n')).
rewrite mult_plus_distr_r.
apply f_equal2.
* rewrite (mult_comm x). rewrite <- mult_assoc. apply f_equal2.
{ reflexivity. }
{ rewrite <- mult_assoc. rewrite (mult_comm _ x).
rewrite mult_assoc. apply f_equal2.
rewrite <- minus_Sn_m. rewrite mult_comm. reflexivity. apply Hi.
reflexivity. }
* rewrite (mult_comm y). rewrite <- mult_assoc. apply f_equal2.
{ reflexivity. }
{ rewrite <- mult_assoc. apply f_equal2. reflexivity.
rewrite mult_comm. reflexivity. }
- reflexivity.
}
Qed.
Exercise: 4 stars (binomial_theorem)
Prove the binomial theorem, i.e., that
exp (x + y) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
sum_nm n 0 (fun k : nat ⇒ choose n k * (exp x (n - k) * exp y k)).
(* FILL IN HERE *)
☐
Lemma exp_one : ∀ n,
exp 1 n = 1.
Proof.
induction n as [|n IHn'].
- reflexivity.
- simpl. rewrite IHn'. reflexivity.
Qed.
Lemma binomial_two_to_the_n : ∀ n,
exp 2 n =
sum_nm n 0 (fun k : nat ⇒ choose n k).
Proof.
intros n.
rewrite → (sum_nm_ext _ _ _ (fun k ⇒ choose n k * (exp 1 (n - k) * exp 1 k))).
apply (binomial 1 1).
intros x Hlt.
simpl. rewrite exp_one. rewrite exp_one. rewrite mult_comm.
rewrite mult_1_l. reflexivity.
Qed.
exp 1 n = 1.
Proof.
induction n as [|n IHn'].
- reflexivity.
- simpl. rewrite IHn'. reflexivity.
Qed.
Lemma binomial_two_to_the_n : ∀ n,
exp 2 n =
sum_nm n 0 (fun k : nat ⇒ choose n k).
Proof.
intros n.
rewrite → (sum_nm_ext _ _ _ (fun k ⇒ choose n k * (exp 1 (n - k) * exp 1 k))).
apply (binomial 1 1).
intros x Hlt.
simpl. rewrite exp_one. rewrite exp_one. rewrite mult_comm.
rewrite mult_1_l. reflexivity.
Qed.
Lemma binomial_x_plus_1 : ∀ x n,
exp (x + 1) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * exp x (n - k)).
Proof.
(* FILL IN HERE *) Admitted.
Lemma binomial_three_to_the_n : ∀ n,
exp 3 n =
sum_nm n 0 (fun k : nat ⇒ choose n k * exp 2 (n - k)).
Proof.
(* FILL IN HERE *) Admitted.
☐
exp (x + 1) n =
sum_nm n 0 (fun k : nat ⇒ choose n k * exp x (n - k)).
Proof.
(* FILL IN HERE *) Admitted.
Lemma binomial_three_to_the_n : ∀ n,
exp 3 n =
sum_nm n 0 (fun k : nat ⇒ choose n k * exp 2 (n - k)).
Proof.
(* FILL IN HERE *) Admitted.