Built with Alectryon, running Coq+SerAPI v8.19.0+0.19.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
[Loading ML file number_string_notation_plugin.cmxs (using legacy method) ... done]
Local Set Universe Minimization ToSet.LocalOpen Scope nat_scope.(** * Factorials *)(** ** Definition *)Fixpointfactorialn :=
match n with
| 0 => 1
| S n => S n * factorial n
end.(** ** Properties *)(** The factorial of [0] is [1]. *)Definitionnat_factorial_zero : factorial 0 = 1 := idpath.(** The factorial of [n + 1] is [n + 1] times the factorial of [n]. *)Definitionnat_factorial_succn : factorial n.+1 = n.+1 * factorial n
:= idpath.(** A variant of [nat_factorial_succ]. *)
n: nat
0 < n -> factorial n = n * factorial (nat_pred n)
n: nat
0 < n -> factorial n = n * factorial (nat_pred n)
intros []; reflexivity.Defined.(** Every factorial is positive. *)
n: nat
0 < factorial n
n: nat
0 < factorial n
induction n; exact _.Defined.(** Except for [factorial 0 = factorial 1], the [factorial] function is strictly monotone. We separate out the successor case since it is used twice in the proof of the general result. *)
n: nat
0 < n -> factorial n < factorial n.+1
n: nat
0 < n -> factorial n < factorial n.+1
n: nat H: 0 < n
factorial n < factorial n.+1
n: nat H: 0 < n
1 * factorial n < factorial n.+1
rapply (nat_mul_r_strictly_monotone _).Defined.
n, m: nat
0 < n -> n < m -> factorial n < factorial m
n, m: nat
0 < n -> n < m -> factorial n < factorial m
n: nat H1: 0 < n
factorial n < factorial n.+1
n: nat H1: 0 < n m: nat H2: n.+1 <= m IHleq: factorial n < factorial m
factorial n < factorial m.+1
n: nat H1: 0 < n
factorial n < factorial n.+1
rapply nat_factorial_strictly_monotone_succ.
n: nat H1: 0 < n m: nat H2: n.+1 <= m IHleq: factorial n < factorial m
factorial n < factorial m.+1
n: nat H1: 0 < n m: nat H2: n.+1 <= m IHleq: factorial n < factorial m
factorial m < factorial m.+1
rapply nat_factorial_strictly_monotone_succ.Defined.(** ** Divisibility *)(** Any number less than or equal to [n] divides [factorial n]. *)
n, m: nat
0 < n -> n <= m -> (n | factorial m)
n, m: nat
0 < n -> n <= m -> (n | factorial m)
n, m: nat H2: 1 <= m
(1 | factorial m)
n, m, m0: nat l: 1 <= m0 H2: m0.+1 <= m
(m0.+1 | factorial m)
n, m, m0: nat l: 1 <= m0 H2: m0.+1 <= m
(m0.+1 | factorial m)
induction H2; exact _.Defined.(** [factorial] is a monotone function from [nat] to [nat] with respect to [<=] and divides. *)
n, m: nat
n <= m -> (factorial n | factorial m)
n, m: nat
n <= m -> (factorial n | factorial m)
intros H; induction H; exact _.Defined.(** A product of factorials divides the factorial of the sum. *)
n, m: nat
(factorial n * factorial m | factorial (n + m))
n, m: nat
(factorial n * factorial m | factorial (n + m))
n, m, k: nat p: n + m = k
(factorial n * factorial m | factorial k)
k: nat IH: forallm : nat,
m < k ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k
(factorial n * factorial m | factorial k)
IH: forallm : nat,
m < 0 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = 0
(factorial n * factorial m | factorial 0)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
(factorial n * factorial m | factorial k.+1)
IH: forallm : nat,
m < 0 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = 0
(factorial n * factorial m | factorial 0)
IH: forallm : nat,
m < 0 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: ((n = 0) * (m = 0))%type
(factorial n * factorial m | factorial 0)
IH: forallm : nat,
m < 0 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n = 0 q: m = 0
(factorial n * factorial m | factorial 0)
IH: forallm : nat,
m < 0 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) p, q: 0 = 0
(factorial 0 * factorial 0 | factorial 0)
exact _.
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
(factorial n * factorial m | factorial k.+1)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
(factorial n * factorial m | k.+1 * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
(factorial n * factorial m | (n + m) * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
(factorial n * factorial m
| n * factorial k + m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m' | n' * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m
| n * factorial k + m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1
foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m' | n' * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 n', m': nat p': n' + m' = k.+1
(factorial n' * factorial m' | n' * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 n', m': nat p': n'.+1 + m' = k.+1
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 n', m': nat p': n'.+1 + m' = k.+1
(factorial n' * factorial m' | factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 n', m': nat p': n'.+1 + m' = k.+1
n' + m' = k
exact (ap nat_pred p').
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m
| n * factorial k + m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m | n * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m | m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m | n * factorial k)
apply helper, p.
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial n * factorial m | m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
(factorial m * factorial n | m * factorial k)
k: nat IH: forallm : nat,
m < k.+1 ->
forallnm0 : nat,
n + m0 = m ->
(factorial n * factorial m0 | factorial m) n, m: nat p: n + m = k.+1 helper: foralln'm' : nat,
n' + m' = k.+1 ->
(factorial n' * factorial m'
| n' * factorial k)
m + n = k.+1
lhs napply nat_add_comm; exact p.Defined.(** Here is a variant of [nat_divides_factorial_mul_factorial_add] that is more suitable for binomial coefficients. *)
n, m: nat
m <= n ->
(factorial m * factorial (n - m) | factorial n)
n, m: nat
m <= n ->
(factorial m * factorial (n - m) | factorial n)
n, m: nat H: m <= n
(factorial m * factorial (n - m) | factorial n)
n, m: nat H: m <= n
(factorial m * factorial (n - m)
| factorial (m + (n - m)))