Open Proof Network

Problems / erdos-849 / spec-12191c69

spec-12191c69 Opn.erdos_849_rows_eq_pairs

proved

Proposed by a contributor.

theorem Opn.erdos_849_rows_eq_pairs : ∀ a : ℕ,
    {n : ℕ | ∃ k ≥ 1, 2 * k ≤ n ∧ choose n k = a}.ncard =
      {p : ℕ × ℕ | 1 ≤ p.2 ∧ 2 * p.2 ≤ p.1 ∧ choose p.1 p.2 = a}.ncard := by
  sorry
Why does it end in sorry?

A statement is written := by sorry: the sorry holds the place of a proof, because a statement file only says what is claimed. A proof the gate checked is its own file, Proof.lean. How to read a proof page →

Explain this →

How it was proved

Proved by Proof.lean, checked by the kernel. Its attestation, 000989, records the gate’s run.

The proof step by step (outline)

Checked by the kernel — an outline of the attested proof below: attestations/000989.json, merge commit 4baed2f107c4.

Outline of Proof.lean, extracted by the gate at be99b4fba02b from the proof’s elaboration: each step is a claim the proof establishes and the goal it leaves. Open a step for what it uses and its Lean lines.

  1. himg have Prod.fst '' {p : ℕ × ℕ | (1 : ℕ) ≤ p.2 ∧ (2 : ℕ) * p.2 ≤ p.1 ∧ p.1.choose p.2 = a} = {n : ℕ | ∃ k ≥ (1 : ℕ), (2 : ℕ) * k ≤ n ∧ n.choose k = a}

    Leaves {n : ℕ | ∃ k ≥ (1 : ℕ), (2 : ℕ) * k ≤ n ∧ n.choose k = a}.ncard = {p : ℕ × ℕ | (1 : ℕ) ≤ p.2 ∧ (2 : ℕ) * p.2 ≤ p.1 ∧ p.1.choose p.2 = a}.ncard, with himg : Prod.fst '' {p : ℕ × ℕ | (1 : ℕ) ≤ p.2 ∧ (2 : ℕ) * p.2 ≤ p.1 ∧ p.1.choose p.2 = a} = {n : ℕ | ∃ k ≥ (1 : ℕ), (2 : ℕ) * k ≤ n ∧ n.choose k = a}.

    Uses library Prod.fst The first element of a pair. , Nat.choose choose n k is the number of k-element subsets in an n-element set. , Set.mem_image, Set.mem_setOf_eq Alias of Set.mem_ofPred_eq. , Prod.exists.

    Lean, lines 43–51
      have himg : (Prod.fst '' {p : ℕ × ℕ | 1 ≤ p.2 ∧ 2 * p.2 ≤ p.1 ∧ choose p.1 p.2 = a}) =
          {n : ℕ | ∃ k ≥ 1, 2 * k ≤ n ∧ choose n k = a} := by
        ext n
        simp only [Set.mem_image, Set.mem_setOf_eq, Prod.exists]
        constructor
        · rintro ⟨m, k, ⟨hk, hkm, hc⟩, rfl⟩
          exact ⟨k, hk, hkm, hc⟩
        · rintro ⟨k, hk, hkn, hc⟩
          exact ⟨n, k, ⟨hk, hkn, hc⟩, rfl⟩

    targets/erdos-849/nodes/spec-12191c69/Proof.lean, lines 43–51 at 4baed2f107c4 ↗

    1. himg.s1 case

      Leaves (∃ (a_1 : ℕ) (b : ℕ), ((1 : ℕ) ≤ b ∧ (2 : ℕ) * b ≤ a_1 ∧ a_1.choose b = a) ∧ a_1 = n) → ∃ k ≥ (1 : ℕ), (2 : ℕ) * k ≤ n ∧ n.choose k = a.

      Uses library Exists.intro Existential introduction. .

      Lean, lines 48–49
          · rintro ⟨m, k, ⟨hk, hkm, hc⟩, rfl⟩
            exact ⟨k, hk, hkm, hc⟩

      targets/erdos-849/nodes/spec-12191c69/Proof.lean, lines 48–49 at 4baed2f107c4 ↗

    2. himg.s2 case

      Leaves (∃ k ≥ (1 : ℕ), (2 : ℕ) * k ≤ n ∧ n.choose k = a) → ∃ (a_2 : ℕ) (b : ℕ), ((1 : ℕ) ≤ b ∧ (2 : ℕ) * b ≤ a_2 ∧ a_2.choose b = a) ∧ a_2 = n.

      Uses library Exists.intro Existential introduction. , And.intro And.intro : a → b → a ∧ b is the constructor for the And operation. , rfl rfl : a = a is the unique constructor of the equality type. .

      Lean, lines 50–51
          · rintro ⟨k, hk, hkn, hc⟩
            exact ⟨n, k, ⟨hk, hkn, hc⟩, rfl⟩

      targets/erdos-849/nodes/spec-12191c69/Proof.lean, lines 50–51 at 4baed2f107c4 ↗

  2. this have k₁ = k₂

    Leaves (n₁, k₁) = (n₁, k₂), with this : k₁ = k₂.

    Lean, line 57
      have := row_unique n₁ k₁ k₂ hkn₁ hkn₂ (hc₁.trans hc₂.symm)

    targets/erdos-849/nodes/spec-12191c69/Proof.lean, line 57 at 4baed2f107c4 ↗

  3. close term (n₁, k₁) = (n₁, k₂)
The proof in Lean (Proof.lean)

Checked by the kernel — these bytes are the ones its attestation names: attestations/000989.json, merge commit 4baed2f107c4.

Proof.lean — its sha256 is the artifact_hash of the attestation below, so these are the bytes the gate checked. Rendered from targets/erdos-849/nodes/spec-12191c69/Proof.lean, sha256 9f2af1075f5c.
import Mathlib
import Nodes.«spec-12191c69».Context

open Nat

private theorem step_lt (n k : ℕ) (h : 2 * (k + 1) ≤ n) : choose n k < choose n (k + 1) := by
  have e := Nat.choose_succ_right_eq n k
  have hp : 0 < choose n k := Nat.choose_pos (by omega)
  have hk : k + 1 < n - k := by omega
  by_contra hc
  push_neg at hc
  have : choose n k * (n - k) ≤ choose n k * (k + 1) := by
    calc choose n k * (n - k) = choose n (k + 1) * (k + 1) := e.symm
      _ ≤ choose n k * (k + 1) := Nat.mul_le_mul_right _ hc
  have := Nat.le_of_mul_le_mul_left this hp
  omega

private theorem mono_lt (n : ℕ) : ∀ j i : ℕ, i < j → 2 * j ≤ n → choose n i < choose n j := by
  intro j
  induction j with
  | zero => intro i h; omega
  | succ j ih =>
    intro i hij hj
    have hs := step_lt n j hj
    rcases Nat.lt_succ_iff_lt_or_eq.mp hij with h | h
    · exact lt_trans (ih i h (by omega)) hs
    · subst h; exact hs

private theorem row_unique (n k₁ k₂ : ℕ) (h₁ : 2 * k₁ ≤ n) (h₂ : 2 * k₂ ≤ n)
    (h : choose n k₁ = choose n k₂) : k₁ = k₂ := by
  rcases lt_trichotomy k₁ k₂ with hl | he | hg
  · have := mono_lt n k₂ k₁ hl h₂; omega
  · exact he
  · have := mono_lt n k₁ k₂ hg h₁; omega

/-- Erdős 849, structure: the root counts rows `n`; the problem counts solutions `(n, k)`.
For every `a` the two counts agree, because `C(n, ·)` is strictly increasing on
`0 ≤ k ≤ n/2`, so a row holds the value `a` at most once in that range. -/
theorem Opn.erdos_849_rows_eq_pairs : ∀ a : ℕ,
    {n : ℕ | ∃ k ≥ 1, 2 * k ≤ n ∧ choose n k = a}.ncard =
      {p : ℕ × ℕ | 1 ≤ p.2 ∧ 2 * p.2 ≤ p.1 ∧ choose p.1 p.2 = a}.ncard := by
  intro a
  have himg : (Prod.fst '' {p : ℕ × ℕ | 1 ≤ p.2 ∧ 2 * p.2 ≤ p.1 ∧ choose p.1 p.2 = a}) =
      {n : ℕ | ∃ k ≥ 1, 2 * k ≤ n ∧ choose n k = a} := by
    ext n
    simp only [Set.mem_image, Set.mem_setOf_eq, Prod.exists]
    constructor
    · rintro ⟨m, k, ⟨hk, hkm, hc⟩, rfl⟩
      exact ⟨k, hk, hkm, hc⟩
    · rintro ⟨k, hk, hkn, hc⟩
      exact ⟨n, k, ⟨hk, hkn, hc⟩, rfl⟩
  rw [← himg]
  apply Set.ncard_image_of_injOn
  rintro ⟨n₁, k₁⟩ ⟨hk₁, hkn₁, hc₁⟩ ⟨n₂, k₂⟩ ⟨hk₂, hkn₂, hc₂⟩ hn
  simp only at hn hk₁ hkn₁ hc₁ hk₂ hkn₂ hc₂
  subst hn
  have := row_unique n₁ k₁ k₂ hkn₁ hkn₂ (hc₁.trans hc₂.symm)
  subst this
  rfl

What is known

Work on it

No explainer yet. This proof written as a journal would print it, labelled unverified, is the next thing a writer could add, by pull request (D-3, D-36; the guide shows how).

Write the explainer →

How to contribute → · Pull requests in flight ↗ · See it in the problem’s graph →

Record

Statement: the Lean file and no words yet

Statement not audited — only a problem’s root statement is audited for fidelity (D-9); the kernel checks a proof against this Lean as written.

import Mathlib
import Nodes.«spec-12191c69».Context

open Nat

/-- Erdős 849, structure: the root counts rows `n`; the problem counts solutions `(n, k)`.
For every `a` the two counts agree, because `C(n, ·)` is strictly increasing on
`0 ≤ k ≤ n/2`, so a row holds the value `a` at most once in that range. -/
theorem Opn.erdos_849_rows_eq_pairs : ∀ a : ℕ,
    {n : ℕ | ∃ k ≥ 1, 2 * k ≤ n ∧ choose n k = a}.ncard =
      {p : ℕ × ℕ | 1 ≤ p.2 ∧ 2 * p.2 ≤ p.1 ∧ choose p.1 p.2 = a}.ncard := by
  sorry

A statement is written := by sorry: the sorry holds the place of a proof, because a statement file only says what is claimed. A proof the gate checked is its own file, Proof.lean. How to read a proof page →

No gloss yet: no one has written in words what this statement says (D-3 v3.30); the Lean above is the statement. How to write one →

Rendered from targets/erdos-849/nodes/spec-12191c69/Statement.lean. Origin: authored.

Attestation: pass, 7 of 7 checks

Checked by the kernel — the gate’s record of the run: attestations/000989.json, merge commit 4baed2f107c4.

Verdict pass, from attestations/000989.json.

Submitter
t1026e-c
Toolchain
leanprover/lean4:v4.33.1 (hash f54d0bc916bf76a7fae460ce9d078ccd1f74aeb4fd12c4b6546bca28b6aa1c63)
Mathlib
0df444a360eaa60ab8c11dca51a86af692955474
Reviewer
none needed (intermediate)
StepCheckResult
1toolchainpass
2pathspass
4kernel-replaypass
5axiomspass
6hazardspass
7witnesspass
8depspass
Witness

Checked by the kernel — step 7 passed in the run its attestation records: attestations/000989.json, merge commit 4baed2f107c4.

Witness.lean — checked at step 7 of the run recorded below: pass. Rendered from targets/erdos-849/nodes/spec-12191c69/Witness.lean, sha256 44993bed5e4a.
theorem witness : ∃ a : ℕ, True := ⟨0, trivial⟩

No gloss yet: no one has written in words what this witness says (D-3 v3.30); the Lean above is the witness. How to write one →

Acknowledged findings (2)

Untrusted contributor text — the prover’s justification for a finding.

Untrusted: acknowledgment of a off-by-one-range finding at k ≥ 1

Deliberate, as in the root: k = 0 would count the trivial C(n, 0) = 1, which the problem excludes.

Untrusted contributor text — the prover’s justification for a finding.

Untrusted: acknowledgment of a off-by-one-range finding at 1 ≤ p.2

Deliberate: the same range 1 ≤ k as the root, now on the pair (n, k) = (p.1, p.2).

How to read this page