File: Mathlib/Computability/Ackermann.lean

full_name: ack
code: /-- The two-argument Ackermann function, defined so that

- `ack 0 n = n + 1`
- `ack (m + 1) 0 = ack m 1`
- `ack (m + 1) (n + 1) = ack m (ack (m + 1) n)`.

This is of interest as both a fast-growing function, and as an example of a recursive function that
isn't primitive recursive. -/
def ack : ℕ → ℕ → ℕ
  
goal: ℕ → ℕ → ℕ

full_name: ack_zero
code: @[simp]
theorem ack_zero (n : ℕ) : ack 0 n = n + 1 
goal: ack 0 n = n + 1

full_name: ack_succ_zero
code: @[simp]
theorem ack_succ_zero (m : ℕ) : ack (m + 1) 0 = ack m 1 
goal: ack (m + 1) 0 = ack m 1

full_name: ack_succ_succ
code: @[simp]
theorem ack_succ_succ (m n : ℕ) : ack (m + 1) (n + 1) = ack m (ack (m + 1) n) 
goal: ack (m + 1) (n + 1) = ack m (ack (m + 1) n)

full_name: ack_one
code: @[simp]
theorem ack_one (n : ℕ) : ack 1 n = n + 2 
goal: ack 1 n = n + 2

full_name: ack_two
code: @[simp]
theorem ack_two (n : ℕ) : ack 2 n = 2 * n + 3 
goal: ack 2 n = 2 * n + 3

full_name: ack_three
code: @[simp]
theorem ack_three (n : ℕ) : ack 3 n = 2 ^ (n + 3) - 3 
goal: ack 3 n = 2 ^ (n + 3) - 3

full_name: ack_pos
code: theorem ack_pos : ∀ m n, 0 < ack m n
  
goal: 0 < ack m n

full_name: one_lt_ack_succ_left
code: theorem one_lt_ack_succ_left : ∀ m n, 1 < ack (m + 1) n
  
goal: 1 < ack (m + 1) n

full_name: one_lt_ack_succ_right
code: theorem one_lt_ack_succ_right : ∀ m n, 1 < ack m (n + 1)
  
goal: 1 < ack m (n + 1)

full_name: ack_strictMono_right
code: theorem ack_strictMono_right : ∀ m, StrictMono (ack m)
  
goal: StrictMono (ack m)

full_name: ack_mono_right
code: theorem ack_mono_right (m : ℕ) : Monotone (ack m) 
goal: Monotone (ack m)

full_name: ack_injective_right
code: theorem ack_injective_right (m : ℕ) : Function.Injective (ack m) 
goal: Function.Injective (ack m)

full_name: ack_lt_iff_right
code: @[simp]
theorem ack_lt_iff_right {m n₁ n₂ : ℕ} : ack m n₁ < ack m n₂ ↔ n₁ < n₂ 
goal: ack m n₁ < ack m n₂ ↔ n₁ < n₂

full_name: ack_le_iff_right
code: @[simp]
theorem ack_le_iff_right {m n₁ n₂ : ℕ} : ack m n₁ ≤ ack m n₂ ↔ n₁ ≤ n₂ 
goal: ack m n₁ ≤ ack m n₂ ↔ n₁ ≤ n₂

full_name: ack_inj_right
code: @[simp]
theorem ack_inj_right {m n₁ n₂ : ℕ} : ack m n₁ = ack m n₂ ↔ n₁ = n₂ 
goal: ack m n₁ = ack m n₂ ↔ n₁ = n₂

full_name: max_ack_right
code: theorem max_ack_right (m n₁ n₂ : ℕ) : ack m (max n₁ n₂) = max (ack m n₁) (ack m n₂) 
goal: ack m (max n₁ n₂) = max (ack m n₁) (ack m n₂)

full_name: add_lt_ack
code: theorem add_lt_ack : ∀ m n, m + n < ack m n
  
goal: m + n < ack m n

full_name: add_add_one_le_ack
code: theorem add_add_one_le_ack (m n : ℕ) : m + n + 1 ≤ ack m n 
goal: m + n + 1 ≤ ack m n

full_name: lt_ack_left
code: theorem lt_ack_left (m n : ℕ) : m < ack m n 
goal: m < ack m n

full_name: lt_ack_right
code: theorem lt_ack_right (m n : ℕ) : n < ack m n 
goal: n < ack m n

full_name: _private.Mathlib.Computability.Ackermann.0.ack_strict_mono_left'
code: private theorem ack_strict_mono_left' : ∀ {m₁ m₂} (n), m₁ < m₂ → ack m₁ n < ack m₂ n
  
goal: m₁ < m₂ → ack m₁ n < ack m₂ n

full_name: ack_strictMono_left
code: theorem ack_strictMono_left (n : ℕ) : StrictMono fun m => ack m n 
goal: StrictMono fun m => ack m n

full_name: ack_mono_left
code: theorem ack_mono_left (n : ℕ) : Monotone fun m => ack m n 
goal: Monotone fun m => ack m n

full_name: ack_injective_left
code: theorem ack_injective_left (n : ℕ) : Function.Injective fun m => ack m n 
goal: Function.Injective fun m => ack m n

full_name: ack_lt_iff_left
code: @[simp]
theorem ack_lt_iff_left {m₁ m₂ n : ℕ} : ack m₁ n < ack m₂ n ↔ m₁ < m₂ 
goal: ack m₁ n < ack m₂ n ↔ m₁ < m₂

full_name: ack_le_iff_left
code: @[simp]
theorem ack_le_iff_left {m₁ m₂ n : ℕ} : ack m₁ n ≤ ack m₂ n ↔ m₁ ≤ m₂ 
goal: ack m₁ n ≤ ack m₂ n ↔ m₁ ≤ m₂

full_name: ack_inj_left
code: @[simp]
theorem ack_inj_left {m₁ m₂ n : ℕ} : ack m₁ n = ack m₂ n ↔ m₁ = m₂ 
goal: ack m₁ n = ack m₂ n ↔ m₁ = m₂

full_name: max_ack_left
code: theorem max_ack_left (m₁ m₂ n : ℕ) : ack (max m₁ m₂) n = max (ack m₁ n) (ack m₂ n) 
goal: ack (max m₁ m₂) n = max (ack m₁ n) (ack m₂ n)

full_name: ack_le_ack
code: theorem ack_le_ack {m₁ m₂ n₁ n₂ : ℕ} (hm : m₁ ≤ m₂) (hn : n₁ ≤ n₂) : ack m₁ n₁ ≤ ack m₂ n₂ 
goal: ack m₁ n₁ ≤ ack m₂ n₂

full_name: ack_succ_right_le_ack_succ_left
code: theorem ack_succ_right_le_ack_succ_left (m n : ℕ) : ack m (n + 1) ≤ ack (m + 1) n 
goal: ack m (n + 1) ≤ ack (m + 1) n

full_name: _private.Mathlib.Computability.Ackermann.0.sq_le_two_pow_add_one_minus_three
code: private theorem sq_le_two_pow_add_one_minus_three (n : ℕ) : n ^ 2 ≤ 2 ^ (n + 1) - 3 
goal: n ^ 2 ≤ 2 ^ (n + 1) - 3

full_name: ack_add_one_sq_lt_ack_add_three
code: theorem ack_add_one_sq_lt_ack_add_three : ∀ m n, (ack m n + 1) ^ 2 ≤ ack (m + 3) n
  
goal: (ack m n + 1) ^ 2 ≤ ack (m + 3) n

full_name: ack_ack_lt_ack_max_add_two
code: theorem ack_ack_lt_ack_max_add_two (m n k : ℕ) : ack m (ack n k) < ack (max m n + 2) k 
goal: ack m (ack n k) < ack (max m n + 2) k

full_name: ack_add_one_sq_lt_ack_add_four
code: theorem ack_add_one_sq_lt_ack_add_four (m n : ℕ) : ack m ((n + 1) ^ 2) < ack (m + 4) n 
goal: ack m ((n + 1) ^ 2) < ack (m + 4) n

full_name: ack_pair_lt
code: theorem ack_pair_lt (m n k : ℕ) : ack m (pair n k) < ack (m + 4) (max n k) 
goal: ack m (Nat.pair n k) < ack (m + 4) (max n k)

full_name: exists_lt_ack_of_nat_primrec
code: /-- If `f` is primitive recursive, there exists `m` such that `f n < ack m n` for all `n`. -/
theorem exists_lt_ack_of_nat_primrec {f : ℕ → ℕ} (hf : Nat.Primrec f) :
    ∃ m, ∀ n, f n < ack m n 
goal: ∃ m, ∀ (n : ℕ), f n < ack m n

full_name: not_nat_primrec_ack_self
code: theorem not_nat_primrec_ack_self : ¬Nat.Primrec fun n => ack n n 
goal: ¬Nat.Primrec fun n => ack n n

full_name: not_primrec_ack_self
code: theorem not_primrec_ack_self : ¬Primrec fun n => ack n n 
goal: ¬Primrec fun n => ack n n

full_name: not_primrec₂_ack
code: /-- The Ackermann function is not primitive recursive. -/
theorem not_primrec₂_ack : ¬Primrec₂ ack 
goal: ¬Primrec₂ ack